blob: 40c1f774e0c022dec66b43b71f1a052bc01c3f01 [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
215 // Create mock services
216 MockServices services{};
217
218 // Expect Sensors service to be called 5+5=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);
223
224 // Expect Journal service to be called 3+3=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);
229
230 // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
231 MockErrorLogging& errorLogging = services.getMockErrorLogging();
232 EXPECT_CALL(errorLogging, logDBusError).Times(2);
233
234 // Monitor sensors 5 times. Should fail every time, write to journal 3
235 // times, and log one error.
236 for (int i = 1; i <= 5; ++i)
237 {
Shawn McCarney83058602021-09-09 20:52:45 -0500238 chassis.monitorSensors(services, *system);
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500239 }
240
241 // Clear error history
Shawn McCarney83058602021-09-09 20:52:45 -0500242 chassis.clearErrorHistory();
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500243
244 // Monitor sensors 5 times again. Should fail every time, write to journal
245 // 3 times, and log one error.
246 for (int i = 1; i <= 5; ++i)
247 {
Shawn McCarney83058602021-09-09 20:52:45 -0500248 chassis.monitorSensors(services, *system);
Shawn McCarney9f3e54e2021-05-14 14:56:13 -0500249 }
250}
251
Shawn McCarney83058602021-09-09 20:52:45 -0500252TEST_F(ChassisTests, CloseDevices)
Shawn McCarney050531f2020-06-02 14:17:12 -0500253{
254 // Test where no devices were specified in constructor
255 {
Bob Kingd692d6d2020-09-14 13:42:57 +0800256 // Create mock services. Expect logDebug() to be called.
257 MockServices services{};
258 MockJournal& journal = services.getMockJournal();
259 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
260
Shawn McCarney050531f2020-06-02 14:17:12 -0500261 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500262 Chassis chassis{2, defaultInventoryPath};
Shawn McCarney050531f2020-06-02 14:17:12 -0500263
264 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800265 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500266 }
267
268 // Test where devices were specified in constructor
269 {
270 std::vector<std::unique_ptr<Device>> devices{};
271
Bob Kingd692d6d2020-09-14 13:42:57 +0800272 // Create mock services. Expect logDebug() to be called.
273 MockServices services{};
274 MockJournal& journal = services.getMockJournal();
275 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
276
Shawn McCarney050531f2020-06-02 14:17:12 -0500277 // Create Device vdd0_reg
278 {
279 // Create mock I2CInterface: isOpen() and close() should be called
Shawn McCarney83058602021-09-09 20:52:45 -0500280 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney050531f2020-06-02 14:17:12 -0500281 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
282 EXPECT_CALL(*i2cInterface, close).Times(1);
283
284 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500285 auto device =
Bob Kinga76898f2020-10-13 15:08:33 +0800286 std::make_unique<Device>("vdd0_reg", true,
287 "/xyz/openbmc_project/inventory/"
288 "system/chassis/motherboard/vdd0_reg",
289 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500290 devices.emplace_back(std::move(device));
291 }
292
293 // Create Device vdd1_reg
294 {
295 // Create mock I2CInterface: isOpen() and close() should be called
Shawn McCarney83058602021-09-09 20:52:45 -0500296 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney050531f2020-06-02 14:17:12 -0500297 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
298 EXPECT_CALL(*i2cInterface, close).Times(1);
299
300 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500301 auto device =
Bob Kinga76898f2020-10-13 15:08:33 +0800302 std::make_unique<Device>("vdd1_reg", true,
303 "/xyz/openbmc_project/inventory/"
304 "system/chassis/motherboard/vdd1_reg",
305 std::move(i2cInterface));
Shawn McCarney050531f2020-06-02 14:17:12 -0500306 devices.emplace_back(std::move(device));
307 }
308
309 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500310 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney050531f2020-06-02 14:17:12 -0500311
312 // Call closeDevices()
Bob Kingd692d6d2020-09-14 13:42:57 +0800313 chassis.closeDevices(services);
Shawn McCarney050531f2020-06-02 14:17:12 -0500314 }
315}
316
Shawn McCarney83058602021-09-09 20:52:45 -0500317TEST_F(ChassisTests, Configure)
Shawn McCarney525e20c2020-04-14 11:05:39 -0500318{
319 // Test where no devices were specified in constructor
320 {
Bob King5cfe5102020-07-30 16:26:18 +0800321 // Create mock services. Expect logInfo() to be called.
Bob King23243f82020-07-29 10:38:57 +0800322 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800323 MockJournal& journal = services.getMockJournal();
324 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
325 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
326 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800327
Shawn McCarney525e20c2020-04-14 11:05:39 -0500328 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500329 Chassis chassis{1, defaultInventoryPath};
Shawn McCarney525e20c2020-04-14 11:05:39 -0500330
331 // Call configure()
Shawn McCarney83058602021-09-09 20:52:45 -0500332 chassis.configure(services, *system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500333 }
334
335 // Test where devices were specified in constructor
336 {
337 std::vector<std::unique_ptr<Device>> devices{};
338
Bob King5cfe5102020-07-30 16:26:18 +0800339 // Create mock services. Expect logInfo() and logDebug() to be called.
340 MockServices services{};
341 MockJournal& journal = services.getMockJournal();
342 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
343 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
344 .Times(1);
345 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
346 .Times(1);
347 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
348
Shawn McCarney525e20c2020-04-14 11:05:39 -0500349 // Create Device vdd0_reg
350 {
351 // Create Configuration
352 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney83058602021-09-09 20:52:45 -0500353 auto configuration =
Shawn McCarney525e20c2020-04-14 11:05:39 -0500354 std::make_unique<Configuration>(1.3, std::move(actions));
355
356 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500357 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney525e20c2020-04-14 11:05:39 -0500358 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney83058602021-09-09 20:52:45 -0500359 auto device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800360 "vdd0_reg", true,
361 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
362 "vdd0_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500363 std::move(i2cInterface), std::move(presenceDetection),
364 std::move(configuration));
365 devices.emplace_back(std::move(device));
366 }
367
368 // Create Device vdd1_reg
369 {
370 // Create Configuration
371 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney83058602021-09-09 20:52:45 -0500372 auto configuration =
Shawn McCarney525e20c2020-04-14 11:05:39 -0500373 std::make_unique<Configuration>(1.2, std::move(actions));
374
375 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500376 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney525e20c2020-04-14 11:05:39 -0500377 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney83058602021-09-09 20:52:45 -0500378 auto device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800379 "vdd1_reg", true,
380 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
381 "vdd1_reg",
Shawn McCarney525e20c2020-04-14 11:05:39 -0500382 std::move(i2cInterface), std::move(presenceDetection),
383 std::move(configuration));
384 devices.emplace_back(std::move(device));
385 }
386
387 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500388 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
Shawn McCarney525e20c2020-04-14 11:05:39 -0500389
390 // Call configure()
Shawn McCarney83058602021-09-09 20:52:45 -0500391 chassis.configure(services, *system);
Shawn McCarney525e20c2020-04-14 11:05:39 -0500392 }
393}
394
Shawn McCarney50e57c62021-09-09 22:53:42 -0500395TEST_F(ChassisTests, DetectPhaseFaults)
396{
397 // Test where no devices were specified in constructor
398 {
399 // Create mock services. No errors should be logged.
400 MockServices services{};
401 MockJournal& journal = services.getMockJournal();
402 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
403 MockErrorLogging& errorLogging = services.getMockErrorLogging();
404 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
405
406 // Create Chassis
407 Chassis chassis{1, defaultInventoryPath};
408
409 // Call detectPhaseFaults() 5 times. Should do nothing.
410 for (int i = 1; i <= 5; ++i)
411 {
412 chassis.detectPhaseFaults(services, *system);
413 }
414 }
415
416 // Test where devices were specified in constructor
417 {
418 // Create mock services with the following expectations:
419 // - 2 error messages in journal for N phase fault detected in reg0
420 // - 2 error messages in journal for N phase fault detected in reg1
421 // - 1 N phase fault error logged for reg0
422 // - 1 N phase fault error logged for reg1
423 MockServices services{};
424 MockJournal& journal = services.getMockJournal();
425 EXPECT_CALL(
426 journal,
427 logError("n phase fault detected in regulator reg0: count=1"))
428 .Times(1);
429 EXPECT_CALL(
430 journal,
431 logError("n phase fault detected in regulator reg0: count=2"))
432 .Times(1);
433 EXPECT_CALL(
434 journal,
435 logError("n phase fault detected in regulator reg1: count=1"))
436 .Times(1);
437 EXPECT_CALL(
438 journal,
439 logError("n phase fault detected in regulator reg1: count=2"))
440 .Times(1);
441 MockErrorLogging& errorLogging = services.getMockErrorLogging();
442 EXPECT_CALL(errorLogging, logPhaseFault).Times(2);
443
444 std::vector<std::unique_ptr<Device>> devices{};
445
446 // Create Device reg0
447 {
448 // Create PhaseFaultDetection
449 auto action =
450 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
451 std::vector<std::unique_ptr<Action>> actions{};
452 actions.push_back(std::move(action));
453 auto phaseFaultDetection =
454 std::make_unique<PhaseFaultDetection>(std::move(actions));
455
456 // Create Device
457 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
458 std::unique_ptr<PresenceDetection> presenceDetection{};
459 std::unique_ptr<Configuration> configuration{};
460 auto device = std::make_unique<Device>(
461 "reg0", true,
462 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
463 "reg0",
464 std::move(i2cInterface), std::move(presenceDetection),
465 std::move(configuration), std::move(phaseFaultDetection));
466 devices.emplace_back(std::move(device));
467 }
468
469 // Create Device reg1
470 {
471 // Create PhaseFaultDetection
472 auto action =
473 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
474 std::vector<std::unique_ptr<Action>> actions{};
475 actions.push_back(std::move(action));
476 auto phaseFaultDetection =
477 std::make_unique<PhaseFaultDetection>(std::move(actions));
478
479 // Create Device
480 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
481 std::unique_ptr<PresenceDetection> presenceDetection{};
482 std::unique_ptr<Configuration> configuration{};
483 auto device = std::make_unique<Device>(
484 "reg1", true,
485 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
486 "reg1",
487 std::move(i2cInterface), std::move(presenceDetection),
488 std::move(configuration), std::move(phaseFaultDetection));
489 devices.emplace_back(std::move(device));
490 }
491
492 // Create Chassis
493 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
494
495 // Call detectPhaseFaults() 5 times
496 for (int i = 1; i <= 5; ++i)
497 {
498 chassis.detectPhaseFaults(services, *system);
499 }
500 }
501}
502
Shawn McCarney83058602021-09-09 20:52:45 -0500503TEST_F(ChassisTests, GetDevices)
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500504{
505 // Test where no devices were specified in constructor
506 {
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500507 Chassis chassis{2, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500508 EXPECT_EQ(chassis.getDevices().size(), 0);
509 }
510
511 // Test where devices were specified in constructor
512 {
513 // Create vector of Device objects
514 std::vector<std::unique_ptr<Device>> devices{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500515 devices.emplace_back(createDevice("vdd_reg1"));
516 devices.emplace_back(createDevice("vdd_reg2"));
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500517
518 // Create Chassis
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500519 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500520 EXPECT_EQ(chassis.getDevices().size(), 2);
521 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
522 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
523 }
524}
525
Shawn McCarney83058602021-09-09 20:52:45 -0500526TEST_F(ChassisTests, GetInventoryPath)
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500527{
528 Chassis chassis{3, defaultInventoryPath};
529 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
530}
531
Shawn McCarney83058602021-09-09 20:52:45 -0500532TEST_F(ChassisTests, GetNumber)
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500533{
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500534 Chassis chassis{3, defaultInventoryPath};
Shawn McCarney8a3afd72020-03-12 14:28:44 -0500535 EXPECT_EQ(chassis.getNumber(), 3);
536}
Bob Kinga2c81a62020-07-08 13:31:16 +0800537
Shawn McCarney83058602021-09-09 20:52:45 -0500538TEST_F(ChassisTests, MonitorSensors)
Bob Kinga2c81a62020-07-08 13:31:16 +0800539{
540 // Test where no devices were specified in constructor
541 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500542 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800543 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500544 MockSensors& sensors = services.getMockSensors();
545 EXPECT_CALL(sensors, startRail).Times(0);
546 EXPECT_CALL(sensors, setValue).Times(0);
547 EXPECT_CALL(sensors, endRail).Times(0);
Bob King8a552922020-08-05 17:02:31 +0800548
Bob Kinga2c81a62020-07-08 13:31:16 +0800549 // Create Chassis
Shawn McCarney83058602021-09-09 20:52:45 -0500550 Chassis chassis{1, defaultInventoryPath};
Bob Kinga2c81a62020-07-08 13:31:16 +0800551
552 // Call monitorSensors(). Should do nothing.
Shawn McCarney83058602021-09-09 20:52:45 -0500553 chassis.monitorSensors(services, *system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800554 }
555
556 // Test where devices were specified in constructor
557 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500558 // Create mock services. Set Sensors service expectations.
Bob King8a552922020-08-05 17:02:31 +0800559 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500560 MockSensors& sensors = services.getMockSensors();
561 EXPECT_CALL(sensors, startRail("vdd0",
562 "/xyz/openbmc_project/inventory/system/"
563 "chassis/motherboard/vdd0_reg",
564 defaultInventoryPath))
565 .Times(1);
566 EXPECT_CALL(sensors, startRail("vdd1",
567 "/xyz/openbmc_project/inventory/system/"
568 "chassis/motherboard/vdd1_reg",
569 defaultInventoryPath))
570 .Times(1);
571 EXPECT_CALL(sensors, setValue).Times(0);
572 EXPECT_CALL(sensors, endRail(false)).Times(2);
Bob King8a552922020-08-05 17:02:31 +0800573
Bob Kinga2c81a62020-07-08 13:31:16 +0800574 std::vector<std::unique_ptr<Device>> devices{};
575
Shawn McCarney17bac892021-05-08 07:55:52 -0500576 // Create Device vdd0_reg
577 {
578 // Create SensorMonitoring for Rail
Shawn McCarney83058602021-09-09 20:52:45 -0500579 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500580 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
581 std::vector<std::unique_ptr<Action>> actions{};
582 actions.emplace_back(std::move(action));
Shawn McCarney83058602021-09-09 20:52:45 -0500583 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500584 std::make_unique<SensorMonitoring>(std::move(actions));
Bob Kinga2c81a62020-07-08 13:31:16 +0800585
Shawn McCarney17bac892021-05-08 07:55:52 -0500586 // Create Rail
587 std::unique_ptr<Configuration> configuration{};
Shawn McCarney83058602021-09-09 20:52:45 -0500588 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
589 std::move(sensorMonitoring));
Bob Kinga2c81a62020-07-08 13:31:16 +0800590
Shawn McCarney17bac892021-05-08 07:55:52 -0500591 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500592 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500593 std::unique_ptr<PresenceDetection> presenceDetection{};
594 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500595 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500596 std::vector<std::unique_ptr<Rail>> rails{};
597 rails.emplace_back(std::move(rail));
Shawn McCarney83058602021-09-09 20:52:45 -0500598 auto device = std::make_unique<Device>(
Shawn McCarney17bac892021-05-08 07:55:52 -0500599 "vdd0_reg", true,
600 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
601 "vdd0_reg",
602 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500603 std::move(deviceConfiguration), std::move(phaseFaultDetection),
604 std::move(rails));
Shawn McCarney17bac892021-05-08 07:55:52 -0500605 devices.emplace_back(std::move(device));
606 }
Bob Kinga2c81a62020-07-08 13:31:16 +0800607
Shawn McCarney17bac892021-05-08 07:55:52 -0500608 // Create Device vdd1_reg
609 {
610 // Create SensorMonitoring for Rail
Shawn McCarney83058602021-09-09 20:52:45 -0500611 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500612 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
613 std::vector<std::unique_ptr<Action>> actions{};
614 actions.emplace_back(std::move(action));
Shawn McCarney83058602021-09-09 20:52:45 -0500615 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500616 std::make_unique<SensorMonitoring>(std::move(actions));
Bob Kinga2c81a62020-07-08 13:31:16 +0800617
Shawn McCarney17bac892021-05-08 07:55:52 -0500618 // Create Rail
619 std::unique_ptr<Configuration> configuration{};
Shawn McCarney83058602021-09-09 20:52:45 -0500620 auto rail = std::make_unique<Rail>("vdd1", std::move(configuration),
621 std::move(sensorMonitoring));
Bob Kinga2c81a62020-07-08 13:31:16 +0800622
Shawn McCarney17bac892021-05-08 07:55:52 -0500623 // Create Device
Shawn McCarney83058602021-09-09 20:52:45 -0500624 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500625 std::unique_ptr<PresenceDetection> presenceDetection{};
626 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500627 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500628 std::vector<std::unique_ptr<Rail>> rails{};
629 rails.emplace_back(std::move(rail));
Shawn McCarney83058602021-09-09 20:52:45 -0500630 auto device = std::make_unique<Device>(
Shawn McCarney17bac892021-05-08 07:55:52 -0500631 "vdd1_reg", true,
632 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
633 "vdd1_reg",
634 std::move(i2cInterface), std::move(presenceDetection),
Shawn McCarney32252592021-09-08 15:29:36 -0500635 std::move(deviceConfiguration), std::move(phaseFaultDetection),
636 std::move(rails));
Shawn McCarney17bac892021-05-08 07:55:52 -0500637 devices.emplace_back(std::move(device));
638 }
639
640 // Create Chassis that contains Devices
Shawn McCarney83058602021-09-09 20:52:45 -0500641 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
Bob Kinga2c81a62020-07-08 13:31:16 +0800642
643 // Call monitorSensors()
Shawn McCarney83058602021-09-09 20:52:45 -0500644 chassis.monitorSensors(services, *system);
Bob Kinga2c81a62020-07-08 13:31:16 +0800645 }
646}