blob: 5aaa2fe292b1999b25039fb52ade0d5e2c02a59f [file] [log] [blame]
Shawn McCarneya2461b32019-10-24 18:53:01 -05001/**
2 * Copyright © 2019 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 McCarney0b1a0e72020-03-11 18:01:44 -050016#include "action.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050017#include "chassis.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050018#include "configuration.hpp"
Shawn McCarneya2461b32019-10-24 18:53:01 -050019#include "device.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060020#include "i2c_interface.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050021#include "id_map.hpp"
Shawn McCarney1fd0b142021-09-09 10:04:22 -050022#include "log_phase_fault_action.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050023#include "mock_action.hpp"
Shawn McCarney81a2f902021-03-23 21:41:34 -050024#include "mock_error_logging.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -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 McCarneyb4d18a42020-06-02 10:27:05 -050028#include "mocked_i2c_interface.hpp"
Shawn McCarney1fd0b142021-09-09 10:04:22 -050029#include "phase_fault.hpp"
Shawn McCarney32252592021-09-08 15:29:36 -050030#include "phase_fault_detection.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050031#include "presence_detection.hpp"
32#include "rail.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050033#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 McCarneyeb7bec42020-04-14 09:38:15 -050036#include "system.hpp"
Shawn McCarney371e2442021-05-14 14:18:07 -050037#include "test_sdbus_error.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050038#include "test_utils.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060039
40#include <memory>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050041#include <optional>
Shawn McCarney525e20c2020-04-14 11:05:39 -050042#include <string>
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060043#include <utility>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050044#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050045
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050046#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050047#include <gtest/gtest.h>
48
49using namespace phosphor::power::regulators;
Shawn McCarney8a3afd72020-03-12 14:28:44 -050050using namespace phosphor::power::regulators::test_utils;
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060051
Bob King8e1cd0b2020-07-08 13:30:27 +080052using ::testing::A;
Shawn McCarney81a2f902021-03-23 21:41:34 -050053using ::testing::Ref;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050054using ::testing::Return;
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050055using ::testing::Throw;
Bob King8e1cd0b2020-07-08 13:30:27 +080056using ::testing::TypedEq;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050057
Shawn McCarney2874e902021-09-09 10:03:59 -050058class DeviceTests : public ::testing::Test
59{
60 public:
61 /**
62 * Constructor.
63 *
64 * Creates the Chassis and System objects needed for calling some Device
65 * methods.
66 */
67 DeviceTests() : ::testing::Test{}
68 {
69 // Create Chassis
70 auto chassis = std::make_unique<Chassis>(1, chassisInvPath);
71 this->chassis = chassis.get();
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050072
Shawn McCarney2874e902021-09-09 10:03:59 -050073 // Create System
74 std::vector<std::unique_ptr<Rule>> rules{};
75 std::vector<std::unique_ptr<Chassis>> chassisVec{};
76 chassisVec.emplace_back(std::move(chassis));
Patrick Williams48781ae2023-05-10 07:50:50 -050077 this->system = std::make_unique<System>(std::move(rules),
78 std::move(chassisVec));
Shawn McCarney2874e902021-09-09 10:03:59 -050079 }
80
81 protected:
82 const std::string deviceInvPath{
83 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"};
84 const std::string chassisInvPath{
85 "/xyz/openbmc_project/inventory/system/chassis"};
86
87 // Note: This pointer does NOT need to be explicitly deleted. The Chassis
88 // object is owned by the System object and will be automatically deleted.
89 Chassis* chassis{nullptr};
90
91 std::unique_ptr<System> system{};
92};
93
94TEST_F(DeviceTests, Constructor)
Shawn McCarneya2461b32019-10-24 18:53:01 -050095{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050096 // Test where only required parameters are specified
97 {
98 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
99 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Shawn McCarney2874e902021-09-09 10:03:59 -0500100 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500101 EXPECT_EQ(device.getID(), "vdd_reg");
102 EXPECT_EQ(device.isRegulator(), true);
Shawn McCarney2874e902021-09-09 10:03:59 -0500103 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500104 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
105 EXPECT_EQ(device.getPresenceDetection(), nullptr);
106 EXPECT_EQ(device.getConfiguration(), nullptr);
Shawn McCarney32252592021-09-08 15:29:36 -0500107 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500108 EXPECT_EQ(device.getRails().size(), 0);
109 }
110
111 // Test where all parameters are specified
112 {
113 // Create I2CInterface
114 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
115 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
116
117 // Create PresenceDetection
118 std::vector<std::unique_ptr<Action>> actions{};
119 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500120 auto presenceDetection =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500121 std::make_unique<PresenceDetection>(std::move(actions));
122
123 // Create Configuration
124 std::optional<double> volts{};
125 actions.clear();
126 actions.push_back(std::make_unique<MockAction>());
127 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500128 auto configuration =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500129 std::make_unique<Configuration>(volts, std::move(actions));
130
Shawn McCarney32252592021-09-08 15:29:36 -0500131 // Create PhaseFaultDetection
132 actions.clear();
133 actions.push_back(std::make_unique<MockAction>());
134 actions.push_back(std::make_unique<MockAction>());
135 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500136 auto phaseFaultDetection =
Shawn McCarney32252592021-09-08 15:29:36 -0500137 std::make_unique<PhaseFaultDetection>(std::move(actions));
138
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500139 // Create vector of Rail objects
140 std::vector<std::unique_ptr<Rail>> rails{};
141 rails.push_back(std::make_unique<Rail>("vdd0"));
142 rails.push_back(std::make_unique<Rail>("vdd1"));
143
144 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500145 Device device{"vdd_reg",
146 false,
147 deviceInvPath,
148 std::move(i2cInterface),
149 std::move(presenceDetection),
150 std::move(configuration),
151 std::move(phaseFaultDetection),
152 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500153 EXPECT_EQ(device.getID(), "vdd_reg");
154 EXPECT_EQ(device.isRegulator(), false);
Shawn McCarney2874e902021-09-09 10:03:59 -0500155 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500156 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
157 EXPECT_NE(device.getPresenceDetection(), nullptr);
158 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
159 EXPECT_NE(device.getConfiguration(), nullptr);
160 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
161 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
Shawn McCarney32252592021-09-08 15:29:36 -0500162 EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
163 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 3);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500164 EXPECT_EQ(device.getRails().size(), 2);
165 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500166}
167
Shawn McCarney2874e902021-09-09 10:03:59 -0500168TEST_F(DeviceTests, AddToIDMap)
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500169{
170 std::unique_ptr<PresenceDetection> presenceDetection{};
171 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500172 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500173
174 // Create vector of Rail objects
175 std::vector<std::unique_ptr<Rail>> rails{};
176 rails.push_back(std::make_unique<Rail>("vdd0"));
177 rails.push_back(std::make_unique<Rail>("vdd1"));
178
179 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500180 Device device{"vdd_reg",
181 false,
182 deviceInvPath,
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500183 createI2CInterface(),
Shawn McCarney2874e902021-09-09 10:03:59 -0500184 std::move(presenceDetection),
185 std::move(configuration),
186 std::move(phaseFaultDetection),
187 std::move(rails)};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500188
189 // Add Device and Rail objects to an IDMap
190 IDMap idMap{};
191 device.addToIDMap(idMap);
192
193 // Verify Device is in the IDMap
194 EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
195 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
196
197 // Verify all Rails are in the IDMap
198 EXPECT_NO_THROW(idMap.getRail("vdd0"));
199 EXPECT_NO_THROW(idMap.getRail("vdd1"));
200 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
201}
202
Shawn McCarney2874e902021-09-09 10:03:59 -0500203TEST_F(DeviceTests, ClearCache)
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600204{
205 // Test where Device does not contain a PresenceDetection object
206 try
207 {
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500208 Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600209 device.clearCache();
210 }
211 catch (...)
212 {
213 ADD_FAILURE() << "Should not have caught exception.";
214 }
215
216 // Test where Device contains a PresenceDetection object
217 {
218 // Create PresenceDetection
219 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500220 auto presenceDetection =
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600221 std::make_unique<PresenceDetection>(std::move(actions));
222 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
223
224 // Create Device
225 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500226 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
227 std::move(presenceDetection)};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600228
229 // Cache presence value in PresenceDetection
230 MockServices services{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500231 presenceDetectionPtr->execute(services, *system, *chassis, device);
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600232 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
233
234 // Clear cached data in Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500235 device.clearCache();
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600236
237 // Verify presence value no longer cached in PresenceDetection
238 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
239 }
240}
241
Shawn McCarney2874e902021-09-09 10:03:59 -0500242TEST_F(DeviceTests, ClearErrorHistory)
Shawn McCarney371e2442021-05-14 14:18:07 -0500243{
244 // Create SensorMonitoring. Will fail with a DBus exception.
Shawn McCarney2ee44942021-09-09 17:58:14 -0500245 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
246 {
247 auto action = std::make_unique<MockAction>();
248 EXPECT_CALL(*action, execute)
249 .WillRepeatedly(Throw(TestSDBusError{"DBus Error"}));
250 std::vector<std::unique_ptr<Action>> actions{};
251 actions.emplace_back(std::move(action));
252 sensorMonitoring =
253 std::make_unique<SensorMonitoring>(std::move(actions));
254 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500255
256 // Create Rail
257 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2ee44942021-09-09 17:58:14 -0500258 auto rail = std::make_unique<Rail>("vdd", std::move(configuration),
Shawn McCarney2874e902021-09-09 10:03:59 -0500259 std::move(sensorMonitoring));
Shawn McCarney371e2442021-05-14 14:18:07 -0500260
Shawn McCarney2ee44942021-09-09 17:58:14 -0500261 // Create PhaseFaultDetection. Will log an N phase fault.
262 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
263 {
264 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
265 std::vector<std::unique_ptr<Action>> actions{};
266 actions.emplace_back(std::move(action));
267 phaseFaultDetection =
268 std::make_unique<PhaseFaultDetection>(std::move(actions));
269 }
270
271 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500272 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney371e2442021-05-14 14:18:07 -0500273 std::unique_ptr<PresenceDetection> presenceDetection{};
274 std::unique_ptr<Configuration> deviceConfiguration{};
275 std::vector<std::unique_ptr<Rail>> rails{};
276 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500277 Device device{"reg2",
278 true,
279 deviceInvPath,
280 std::move(i2cInterface),
281 std::move(presenceDetection),
282 std::move(deviceConfiguration),
283 std::move(phaseFaultDetection),
284 std::move(rails)};
Shawn McCarney371e2442021-05-14 14:18:07 -0500285
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500286 // Create lambda that sets MockServices expectations. The lambda allows
287 // us to set expectations multiple times without duplicate code.
Shawn McCarney2ee44942021-09-09 17:58:14 -0500288 auto setExpectations = [](MockServices& services) {
289 // Set Journal service expectations:
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500290 // - 6 error messages for D-Bus errors
291 // - 6 error messages for inability to monitor sensors
Shawn McCarney2ee44942021-09-09 17:58:14 -0500292 // - 2 error messages for the N phase fault
293 MockJournal& journal = services.getMockJournal();
294 EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"}))
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500295 .Times(6);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500296 EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd"))
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500297 .Times(6);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500298 EXPECT_CALL(
299 journal,
300 logError("n phase fault detected in regulator reg2: count=1"))
301 .Times(1);
302 EXPECT_CALL(
303 journal,
304 logError("n phase fault detected in regulator reg2: count=2"))
305 .Times(1);
Shawn McCarney371e2442021-05-14 14:18:07 -0500306
Shawn McCarney2ee44942021-09-09 17:58:14 -0500307 // Set ErrorLogging service expectations:
308 // - D-Bus error should be logged once for the D-Bus exceptions
309 // - N phase fault error should be logged once
310 MockErrorLogging& errorLogging = services.getMockErrorLogging();
311 EXPECT_CALL(errorLogging, logDBusError).Times(1);
312 EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
Shawn McCarney371e2442021-05-14 14:18:07 -0500313
Shawn McCarney2ee44942021-09-09 17:58:14 -0500314 // Set Sensors service expections:
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500315 // - startRail() and endRail() called 10 times
Shawn McCarney2ee44942021-09-09 17:58:14 -0500316 MockSensors& sensors = services.getMockSensors();
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500317 EXPECT_CALL(sensors, startRail).Times(10);
318 EXPECT_CALL(sensors, endRail).Times(10);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500319 };
Shawn McCarney371e2442021-05-14 14:18:07 -0500320
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500321 // Monitor sensors and detect phase faults 10 times. Verify errors logged.
Shawn McCarney371e2442021-05-14 14:18:07 -0500322 {
Shawn McCarney2ee44942021-09-09 17:58:14 -0500323 // Create mock services. Set expectations via lambda.
324 MockServices services{};
325 setExpectations(services);
326
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500327 for (int i = 1; i <= 10; ++i)
Shawn McCarney2ee44942021-09-09 17:58:14 -0500328 {
329 device.monitorSensors(services, *system, *chassis);
330 device.detectPhaseFaults(services, *system, *chassis);
331 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500332 }
333
334 // Clear error history
Shawn McCarney2874e902021-09-09 10:03:59 -0500335 device.clearErrorHistory();
Shawn McCarney371e2442021-05-14 14:18:07 -0500336
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500337 // Monitor sensors and detect phase faults 10 more times. Verify errors
Shawn McCarney2ee44942021-09-09 17:58:14 -0500338 // logged again.
Shawn McCarney371e2442021-05-14 14:18:07 -0500339 {
Shawn McCarney2ee44942021-09-09 17:58:14 -0500340 // Create mock services. Set expectations via lambda.
341 MockServices services{};
342 setExpectations(services);
343
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500344 for (int i = 1; i <= 10; ++i)
Shawn McCarney2ee44942021-09-09 17:58:14 -0500345 {
346 device.monitorSensors(services, *system, *chassis);
347 device.detectPhaseFaults(services, *system, *chassis);
348 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500349 }
350}
351
Shawn McCarney2874e902021-09-09 10:03:59 -0500352TEST_F(DeviceTests, Close)
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500353{
354 // Test where works: I2C interface is not open
355 {
356 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500357 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500358 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
359 EXPECT_CALL(*i2cInterface, close).Times(0);
360
Bob Kingd692d6d2020-09-14 13:42:57 +0800361 // Create mock services. No logError should occur.
362 MockServices services{};
363 MockJournal& journal = services.getMockJournal();
364 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
365 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
366 .Times(0);
367
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500368 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500369 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500370
371 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800372 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500373 }
374
375 // Test where works: I2C interface is open
376 {
377 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500378 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500379 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
380 EXPECT_CALL(*i2cInterface, close).Times(1);
381
Bob Kingd692d6d2020-09-14 13:42:57 +0800382 // Create mock services. No logError should occur.
383 MockServices services{};
384 MockJournal& journal = services.getMockJournal();
385 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
386 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
387 .Times(0);
388
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500389 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500390 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500391
392 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800393 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500394 }
395
396 // Test where fails: closing I2C interface fails
397 {
398 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500399 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500400 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
401 EXPECT_CALL(*i2cInterface, close)
402 .Times(1)
403 .WillOnce(Throw(
404 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
405
Shawn McCarney81a2f902021-03-23 21:41:34 -0500406 // Create mock services. Expect logError() and logI2CError() to be
407 // called.
Bob Kingd692d6d2020-09-14 13:42:57 +0800408 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500409 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob Kingd692d6d2020-09-14 13:42:57 +0800410 MockJournal& journal = services.getMockJournal();
411 std::vector<std::string> expectedErrMessagesException{
412 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
413 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
414 .Times(1);
415 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500416 EXPECT_CALL(errorLogging,
417 logI2CError(Entry::Level::Notice, Ref(journal),
418 "/dev/i2c-1", 0x70, 0))
419 .Times(1);
Bob Kingd692d6d2020-09-14 13:42:57 +0800420
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500421 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500422 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500423
424 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800425 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500426 }
427}
428
Shawn McCarney2874e902021-09-09 10:03:59 -0500429TEST_F(DeviceTests, Configure)
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500430{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600431 // Test where device is not present
432 {
433 // Create mock services. No logging should occur.
434 MockServices services{};
435 MockJournal& journal = services.getMockJournal();
436 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
437 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
438
439 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500440 std::unique_ptr<PresenceDetection> presenceDetection{};
441 {
442 auto action = std::make_unique<MockAction>();
443 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
444 std::vector<std::unique_ptr<Action>> actions{};
445 actions.emplace_back(std::move(action));
446 presenceDetection =
447 std::make_unique<PresenceDetection>(std::move(actions));
448 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600449
450 // Create Configuration. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500451 std::unique_ptr<Configuration> configuration{};
452 {
453 std::optional<double> volts{};
454 auto action = std::make_unique<MockAction>();
455 EXPECT_CALL(*action, execute).Times(0);
456 std::vector<std::unique_ptr<Action>> actions{};
457 actions.emplace_back(std::move(action));
Patrick Williams48781ae2023-05-10 07:50:50 -0500458 configuration = std::make_unique<Configuration>(volts,
459 std::move(actions));
Shawn McCarney2874e902021-09-09 10:03:59 -0500460 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600461
462 // Create Device
463 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500464 Device device{"reg2",
465 true,
466 deviceInvPath,
467 std::move(i2cInterface),
468 std::move(presenceDetection),
469 std::move(configuration)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600470
471 // Call configure(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500472 device.configure(services, *system, *chassis);
Shawn McCarney48033bf2021-01-27 17:56:49 -0600473 }
474
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500475 // Test where Configuration and Rails were not specified in constructor
476 {
Bob King5cfe5102020-07-30 16:26:18 +0800477 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800478 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800479 MockJournal& journal = services.getMockJournal();
480 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
481 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800482
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500483 // Create Device
484 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500485 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500486
Bob King5cfe5102020-07-30 16:26:18 +0800487 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500488 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500489 }
490
491 // Test where Configuration and Rails were specified in constructor
492 {
493 std::vector<std::unique_ptr<Rail>> rails{};
494
Bob King5cfe5102020-07-30 16:26:18 +0800495 // Create mock services. Expect logDebug() to be called.
496 // For the Device and both Rails, should execute the Configuration
497 // and log a debug message.
498 MockServices services{};
499 MockJournal& journal = services.getMockJournal();
Shawn McCarney2874e902021-09-09 10:03:59 -0500500 EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
Bob King5cfe5102020-07-30 16:26:18 +0800501 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
502 .Times(1);
503 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
504 .Times(1);
505 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
506
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500507 // Create Rail vdd0
508 {
509 // Create Configuration for Rail
510 std::optional<double> volts{1.3};
Shawn McCarney2874e902021-09-09 10:03:59 -0500511 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500512 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
513 std::vector<std::unique_ptr<Action>> actions{};
514 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500515 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500516 std::make_unique<Configuration>(volts, std::move(actions));
517
518 // Create Rail
Patrick Williams48781ae2023-05-10 07:50:50 -0500519 auto rail = std::make_unique<Rail>("vdd0",
520 std::move(configuration));
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500521 rails.emplace_back(std::move(rail));
522 }
523
524 // Create Rail vio0
525 {
526 // Create Configuration for Rail
527 std::optional<double> volts{3.2};
Shawn McCarney2874e902021-09-09 10:03:59 -0500528 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500529 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
530 std::vector<std::unique_ptr<Action>> actions{};
531 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500532 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500533 std::make_unique<Configuration>(volts, std::move(actions));
534
535 // Create Rail
Patrick Williams48781ae2023-05-10 07:50:50 -0500536 auto rail = std::make_unique<Rail>("vio0",
537 std::move(configuration));
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500538 rails.emplace_back(std::move(rail));
539 }
540
541 // Create Configuration for Device
542 std::optional<double> volts{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500543 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500544 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
545 std::vector<std::unique_ptr<Action>> actions{};
546 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500547 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500548 std::make_unique<Configuration>(volts, std::move(actions));
549
550 // Create Device
551 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
552 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney32252592021-09-08 15:29:36 -0500553 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500554 Device device{"reg2",
555 true,
556 deviceInvPath,
557 std::move(i2cInterface),
558 std::move(presenceDetection),
559 std::move(configuration),
560 std::move(phaseFaultDetection),
561 std::move(rails)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500562
Bob King5cfe5102020-07-30 16:26:18 +0800563 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500564 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500565 }
566}
567
Shawn McCarney1fd0b142021-09-09 10:04:22 -0500568TEST_F(DeviceTests, DetectPhaseFaults)
569{
570 // Test where device is not present
571 {
572 // Create mock services. No errors should be logged.
573 MockServices services{};
574 MockJournal& journal = services.getMockJournal();
575 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
576 MockErrorLogging& errorLogging = services.getMockErrorLogging();
577 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
578
579 // Create PresenceDetection. Indicates device is not present.
580 std::unique_ptr<PresenceDetection> presenceDetection{};
581 {
582 auto action = std::make_unique<MockAction>();
583 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
584 std::vector<std::unique_ptr<Action>> actions{};
585 actions.emplace_back(std::move(action));
586 presenceDetection =
587 std::make_unique<PresenceDetection>(std::move(actions));
588 }
589
590 // Create PhaseFaultDetection. Action inside it should not be executed.
591 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
592 {
593 auto action = std::make_unique<MockAction>();
594 EXPECT_CALL(*action, execute).Times(0);
595 std::vector<std::unique_ptr<Action>> actions{};
596 actions.emplace_back(std::move(action));
597 phaseFaultDetection =
598 std::make_unique<PhaseFaultDetection>(std::move(actions));
599 }
600
601 // Create Device
602 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
603 std::unique_ptr<Configuration> configuration{};
604 Device device{"reg2",
605 true,
606 deviceInvPath,
607 std::move(i2cInterface),
608 std::move(presenceDetection),
609 std::move(configuration),
610 std::move(phaseFaultDetection)};
611
612 // Call detectPhaseFaults() 5 times. Should do nothing.
613 for (int i = 1; i <= 5; ++i)
614 {
615 device.detectPhaseFaults(services, *system, *chassis);
616 }
617 }
618
619 // Test where PhaseFaultDetection was not specified in constructor
620 {
621 // Create mock services. No errors should be logged.
622 MockServices services{};
623 MockJournal& journal = services.getMockJournal();
624 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
625 MockErrorLogging& errorLogging = services.getMockErrorLogging();
626 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
627
628 // Create Device
629 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
630 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
631
632 // Call detectPhaseFaults() 5 times. Should do nothing.
633 for (int i = 1; i <= 5; ++i)
634 {
635 device.detectPhaseFaults(services, *system, *chassis);
636 }
637 }
638
639 // Test where PhaseFaultDetection was specified in constructor
640 {
641 // Create mock services with the following expectations:
642 // - 2 error messages in journal for N phase fault detected
643 // - 1 N phase fault error logged
644 MockServices services{};
645 MockJournal& journal = services.getMockJournal();
646 EXPECT_CALL(
647 journal,
648 logError("n phase fault detected in regulator reg2: count=1"))
649 .Times(1);
650 EXPECT_CALL(
651 journal,
652 logError("n phase fault detected in regulator reg2: count=2"))
653 .Times(1);
654 MockErrorLogging& errorLogging = services.getMockErrorLogging();
655 EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
656
657 // Create PhaseFaultDetection
658 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
659 std::vector<std::unique_ptr<Action>> actions{};
660 actions.push_back(std::move(action));
661 auto phaseFaultDetection =
662 std::make_unique<PhaseFaultDetection>(std::move(actions));
663
664 // Create Device
665 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
666 std::unique_ptr<PresenceDetection> presenceDetection{};
667 std::unique_ptr<Configuration> configuration{};
668 Device device{"reg2",
669 true,
670 deviceInvPath,
671 std::move(i2cInterface),
672 std::move(presenceDetection),
673 std::move(configuration),
674 std::move(phaseFaultDetection)};
675
676 // Call detectPhaseFaults() 5 times
677 for (int i = 1; i <= 5; ++i)
678 {
679 device.detectPhaseFaults(services, *system, *chassis);
680 }
681 }
682}
683
Shawn McCarney2874e902021-09-09 10:03:59 -0500684TEST_F(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500685{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500686 // Test where Configuration was not specified in constructor
687 {
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500688 Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500689 EXPECT_EQ(device.getConfiguration(), nullptr);
690 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600691
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500692 // Test where Configuration was specified in constructor
693 {
694 std::unique_ptr<PresenceDetection> presenceDetection{};
695
696 // Create Configuration
697 std::optional<double> volts{3.2};
698 std::vector<std::unique_ptr<Action>> actions{};
699 actions.push_back(std::make_unique<MockAction>());
700 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500701 auto configuration =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500702 std::make_unique<Configuration>(volts, std::move(actions));
703
704 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500705 Device device{"vdd_reg",
706 true,
707 deviceInvPath,
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500708 createI2CInterface(),
Shawn McCarney2874e902021-09-09 10:03:59 -0500709 std::move(presenceDetection),
710 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500711 EXPECT_NE(device.getConfiguration(), nullptr);
712 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
713 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
714 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
715 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600716}
717
Shawn McCarney2874e902021-09-09 10:03:59 -0500718TEST_F(DeviceTests, GetFRU)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600719{
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500720 Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
Shawn McCarney2874e902021-09-09 10:03:59 -0500721 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600722}
723
Shawn McCarney2874e902021-09-09 10:03:59 -0500724TEST_F(DeviceTests, GetI2CInterface)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600725{
726 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
727 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Shawn McCarney2874e902021-09-09 10:03:59 -0500728 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600729 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500730}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500731
Shawn McCarney2874e902021-09-09 10:03:59 -0500732TEST_F(DeviceTests, GetID)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500733{
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500734 Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500735 EXPECT_EQ(device.getID(), "vdd_reg");
736}
737
Shawn McCarney2874e902021-09-09 10:03:59 -0500738TEST_F(DeviceTests, GetPhaseFaultDetection)
Shawn McCarney32252592021-09-08 15:29:36 -0500739{
740 // Test where PhaseFaultDetection was not specified in constructor
741 {
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500742 Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
Shawn McCarney32252592021-09-08 15:29:36 -0500743 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
744 }
745
746 // Test where PhaseFaultDetection was specified in constructor
747 {
748 // Create PhaseFaultDetection
749 std::vector<std::unique_ptr<Action>> actions{};
750 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500751 auto phaseFaultDetection =
Shawn McCarney32252592021-09-08 15:29:36 -0500752 std::make_unique<PhaseFaultDetection>(std::move(actions));
753
754 // Create Device
755 std::unique_ptr<PresenceDetection> presenceDetection{};
756 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500757 Device device{"vdd_reg",
758 false,
759 deviceInvPath,
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500760 createI2CInterface(),
Shawn McCarney2874e902021-09-09 10:03:59 -0500761 std::move(presenceDetection),
762 std::move(configuration),
763 std::move(phaseFaultDetection)};
Shawn McCarney32252592021-09-08 15:29:36 -0500764 EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
765 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
766 }
767}
768
Shawn McCarney2874e902021-09-09 10:03:59 -0500769TEST_F(DeviceTests, GetPresenceDetection)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500770{
771 // Test where PresenceDetection was not specified in constructor
772 {
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500773 Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500774 EXPECT_EQ(device.getPresenceDetection(), nullptr);
775 }
776
777 // Test where PresenceDetection was specified in constructor
778 {
779 // Create PresenceDetection
780 std::vector<std::unique_ptr<Action>> actions{};
781 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500782 auto presenceDetection =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500783 std::make_unique<PresenceDetection>(std::move(actions));
784
785 // Create Device
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500786 Device device{"vdd_reg", false, deviceInvPath, createI2CInterface(),
Shawn McCarney2874e902021-09-09 10:03:59 -0500787 std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500788 EXPECT_NE(device.getPresenceDetection(), nullptr);
789 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
790 }
791}
792
Shawn McCarney2874e902021-09-09 10:03:59 -0500793TEST_F(DeviceTests, GetRails)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500794{
795 // Test where no rails were specified in constructor
796 {
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500797 Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500798 EXPECT_EQ(device.getRails().size(), 0);
799 }
800
801 // Test where rails were specified in constructor
802 {
803 std::unique_ptr<PresenceDetection> presenceDetection{};
804 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500805 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500806
807 // Create vector of Rail objects
808 std::vector<std::unique_ptr<Rail>> rails{};
809 rails.push_back(std::make_unique<Rail>("vdd0"));
810 rails.push_back(std::make_unique<Rail>("vdd1"));
811
812 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500813 Device device{"vdd_reg",
814 false,
815 deviceInvPath,
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500816 createI2CInterface(),
Shawn McCarney2874e902021-09-09 10:03:59 -0500817 std::move(presenceDetection),
818 std::move(configuration),
819 std::move(phaseFaultDetection),
820 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500821 EXPECT_EQ(device.getRails().size(), 2);
822 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
823 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
824 }
825}
826
Shawn McCarney2874e902021-09-09 10:03:59 -0500827TEST_F(DeviceTests, IsPresent)
Shawn McCarney48033bf2021-01-27 17:56:49 -0600828{
829 // Test where PresenceDetection not specified in constructor
830 {
831 // Create Device
832 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500833 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600834
835 // Create MockServices
836 MockServices services{};
837
838 // Since no PresenceDetection defined, isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500839 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600840 }
841
842 // Test where PresenceDetection was specified in constructor: Is present
843 {
844 // Create PresenceDetection. Indicates device is present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500845 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600846 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
847 std::vector<std::unique_ptr<Action>> actions{};
848 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500849 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600850 std::make_unique<PresenceDetection>(std::move(actions));
851
852 // Create Device
853 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500854 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
855 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600856
857 // Create MockServices
858 MockServices services{};
859
860 // PresenceDetection::execute() and isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500861 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600862 }
863
864 // Test where PresenceDetection was specified in constructor: Is not present
865 {
866 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500867 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600868 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
869 std::vector<std::unique_ptr<Action>> actions{};
870 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500871 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600872 std::make_unique<PresenceDetection>(std::move(actions));
873
874 // Create Device
875 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500876 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
877 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600878
879 // Create MockServices
880 MockServices services{};
881
882 // PresenceDetection::execute() and isPresent() should return false
Shawn McCarney2874e902021-09-09 10:03:59 -0500883 EXPECT_FALSE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600884 }
885}
886
Shawn McCarney2874e902021-09-09 10:03:59 -0500887TEST_F(DeviceTests, IsRegulator)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500888{
Patrick Williams41a6b9f2023-05-31 19:54:59 -0500889 Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500890 EXPECT_EQ(device.isRegulator(), false);
891}
Bob King8e1cd0b2020-07-08 13:30:27 +0800892
Shawn McCarney2874e902021-09-09 10:03:59 -0500893TEST_F(DeviceTests, MonitorSensors)
Bob King8e1cd0b2020-07-08 13:30:27 +0800894{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600895 // Test where device is not present
Bob King8e1cd0b2020-07-08 13:30:27 +0800896 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500897 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800898 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500899 MockSensors& sensors = services.getMockSensors();
900 EXPECT_CALL(sensors, startRail).Times(0);
901 EXPECT_CALL(sensors, setValue).Times(0);
902 EXPECT_CALL(sensors, endRail).Times(0);
Bob King8a552922020-08-05 17:02:31 +0800903
Shawn McCarney17bac892021-05-08 07:55:52 -0500904 // Create SensorMonitoring. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500905 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
906 {
907 auto action = std::make_unique<MockAction>();
908 EXPECT_CALL(*action, execute).Times(0);
909 std::vector<std::unique_ptr<Action>> actions{};
910 actions.emplace_back(std::move(action));
911 sensorMonitoring =
912 std::make_unique<SensorMonitoring>(std::move(actions));
913 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800914
915 // Create Rail
916 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500917 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
918 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500919
920 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500921 std::unique_ptr<PresenceDetection> presenceDetection{};
922 {
923 auto action = std::make_unique<MockAction>();
924 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
925 std::vector<std::unique_ptr<Action>> actions{};
926 actions.emplace_back(std::move(action));
927 presenceDetection =
928 std::make_unique<PresenceDetection>(std::move(actions));
929 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800930
931 // Create Device
Shawn McCarney17bac892021-05-08 07:55:52 -0500932 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Bob King8e1cd0b2020-07-08 13:30:27 +0800933 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500934 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500935 std::vector<std::unique_ptr<Rail>> rails{};
936 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500937 Device device{"reg2",
938 true,
939 deviceInvPath,
940 std::move(i2cInterface),
941 std::move(presenceDetection),
942 std::move(deviceConfiguration),
943 std::move(phaseFaultDetection),
944 std::move(rails)};
Bob King8e1cd0b2020-07-08 13:30:27 +0800945
Shawn McCarney17bac892021-05-08 07:55:52 -0500946 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500947 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500948 }
949
950 // Test where Rails were not specified in constructor
951 {
952 // Create mock services. No Sensors methods should be called.
953 MockServices services{};
954 MockSensors& sensors = services.getMockSensors();
955 EXPECT_CALL(sensors, startRail).Times(0);
956 EXPECT_CALL(sensors, setValue).Times(0);
957 EXPECT_CALL(sensors, endRail).Times(0);
958
959 // Create Device
960 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500961 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney17bac892021-05-08 07:55:52 -0500962
963 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500964 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500965 }
966
967 // Test where Rails were specified in constructor
968 {
969 // Create mock services. Set Sensors service expectations.
970 MockServices services{};
971 MockSensors& sensors = services.getMockSensors();
Shawn McCarney2874e902021-09-09 10:03:59 -0500972 EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500973 .Times(1);
Shawn McCarney2874e902021-09-09 10:03:59 -0500974 EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500975 .Times(1);
976 EXPECT_CALL(sensors, setValue).Times(0);
977 EXPECT_CALL(sensors, endRail(false)).Times(2);
978
979 std::vector<std::unique_ptr<Rail>> rails{};
980
981 // Create Rail vdd0
982 {
983 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500984 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500985 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
986 std::vector<std::unique_ptr<Action>> actions{};
987 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500988 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500989 std::make_unique<SensorMonitoring>(std::move(actions));
990
991 // Create Rail
992 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500993 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
994 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500995 rails.emplace_back(std::move(rail));
996 }
997
998 // Create Rail vio0
999 {
1000 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -05001001 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -05001002 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
1003 std::vector<std::unique_ptr<Action>> actions{};
1004 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -05001005 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -05001006 std::make_unique<SensorMonitoring>(std::move(actions));
1007
1008 // Create Rail
1009 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -05001010 auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
1011 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -05001012 rails.emplace_back(std::move(rail));
1013 }
1014
1015 // Create Device that contains Rails
1016 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
1017 std::unique_ptr<PresenceDetection> presenceDetection{};
1018 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -05001019 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -05001020 Device device{"reg2",
1021 true,
1022 deviceInvPath,
1023 std::move(i2cInterface),
1024 std::move(presenceDetection),
1025 std::move(configuration),
1026 std::move(phaseFaultDetection),
1027 std::move(rails)};
Shawn McCarney17bac892021-05-08 07:55:52 -05001028
1029 // Call monitorSensors(). Should monitor sensors in both rails.
Shawn McCarney2874e902021-09-09 10:03:59 -05001030 device.monitorSensors(services, *system, *chassis);
Bob King8e1cd0b2020-07-08 13:30:27 +08001031 }
1032}