blob: 0c43b1efe20905427e4cff966c409da76917e78e [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));
77 this->system =
78 std::make_unique<System>(std::move(rules), std::move(chassisVec));
79 }
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,
183 std::move(createI2CInterface()),
184 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 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500208 Device device{"vdd_reg", false, deviceInvPath,
209 std::move(createI2CInterface())};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600210 device.clearCache();
211 }
212 catch (...)
213 {
214 ADD_FAILURE() << "Should not have caught exception.";
215 }
216
217 // Test where Device contains a PresenceDetection object
218 {
219 // Create PresenceDetection
220 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500221 auto presenceDetection =
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600222 std::make_unique<PresenceDetection>(std::move(actions));
223 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
224
225 // Create Device
226 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500227 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
228 std::move(presenceDetection)};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600229
230 // Cache presence value in PresenceDetection
231 MockServices services{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500232 presenceDetectionPtr->execute(services, *system, *chassis, device);
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600233 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
234
235 // Clear cached data in Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500236 device.clearCache();
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600237
238 // Verify presence value no longer cached in PresenceDetection
239 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
240 }
241}
242
Shawn McCarney2874e902021-09-09 10:03:59 -0500243TEST_F(DeviceTests, ClearErrorHistory)
Shawn McCarney371e2442021-05-14 14:18:07 -0500244{
245 // Create SensorMonitoring. Will fail with a DBus exception.
Shawn McCarney2ee44942021-09-09 17:58:14 -0500246 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
247 {
248 auto action = std::make_unique<MockAction>();
249 EXPECT_CALL(*action, execute)
250 .WillRepeatedly(Throw(TestSDBusError{"DBus Error"}));
251 std::vector<std::unique_ptr<Action>> actions{};
252 actions.emplace_back(std::move(action));
253 sensorMonitoring =
254 std::make_unique<SensorMonitoring>(std::move(actions));
255 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500256
257 // Create Rail
258 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2ee44942021-09-09 17:58:14 -0500259 auto rail = std::make_unique<Rail>("vdd", std::move(configuration),
Shawn McCarney2874e902021-09-09 10:03:59 -0500260 std::move(sensorMonitoring));
Shawn McCarney371e2442021-05-14 14:18:07 -0500261
Shawn McCarney2ee44942021-09-09 17:58:14 -0500262 // Create PhaseFaultDetection. Will log an N phase fault.
263 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
264 {
265 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
266 std::vector<std::unique_ptr<Action>> actions{};
267 actions.emplace_back(std::move(action));
268 phaseFaultDetection =
269 std::make_unique<PhaseFaultDetection>(std::move(actions));
270 }
271
272 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500273 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney371e2442021-05-14 14:18:07 -0500274 std::unique_ptr<PresenceDetection> presenceDetection{};
275 std::unique_ptr<Configuration> deviceConfiguration{};
276 std::vector<std::unique_ptr<Rail>> rails{};
277 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500278 Device device{"reg2",
279 true,
280 deviceInvPath,
281 std::move(i2cInterface),
282 std::move(presenceDetection),
283 std::move(deviceConfiguration),
284 std::move(phaseFaultDetection),
285 std::move(rails)};
Shawn McCarney371e2442021-05-14 14:18:07 -0500286
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500287 // Create lambda that sets MockServices expectations. The lambda allows
288 // us to set expectations multiple times without duplicate code.
Shawn McCarney2ee44942021-09-09 17:58:14 -0500289 auto setExpectations = [](MockServices& services) {
290 // Set Journal service expectations:
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500291 // - 6 error messages for D-Bus errors
292 // - 6 error messages for inability to monitor sensors
Shawn McCarney2ee44942021-09-09 17:58:14 -0500293 // - 2 error messages for the N phase fault
294 MockJournal& journal = services.getMockJournal();
295 EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"}))
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500296 .Times(6);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500297 EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd"))
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500298 .Times(6);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500299 EXPECT_CALL(
300 journal,
301 logError("n phase fault detected in regulator reg2: count=1"))
302 .Times(1);
303 EXPECT_CALL(
304 journal,
305 logError("n phase fault detected in regulator reg2: count=2"))
306 .Times(1);
Shawn McCarney371e2442021-05-14 14:18:07 -0500307
Shawn McCarney2ee44942021-09-09 17:58:14 -0500308 // Set ErrorLogging service expectations:
309 // - D-Bus error should be logged once for the D-Bus exceptions
310 // - N phase fault error should be logged once
311 MockErrorLogging& errorLogging = services.getMockErrorLogging();
312 EXPECT_CALL(errorLogging, logDBusError).Times(1);
313 EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
Shawn McCarney371e2442021-05-14 14:18:07 -0500314
Shawn McCarney2ee44942021-09-09 17:58:14 -0500315 // Set Sensors service expections:
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500316 // - startRail() and endRail() called 10 times
Shawn McCarney2ee44942021-09-09 17:58:14 -0500317 MockSensors& sensors = services.getMockSensors();
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500318 EXPECT_CALL(sensors, startRail).Times(10);
319 EXPECT_CALL(sensors, endRail).Times(10);
Shawn McCarney2ee44942021-09-09 17:58:14 -0500320 };
Shawn McCarney371e2442021-05-14 14:18:07 -0500321
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500322 // Monitor sensors and detect phase faults 10 times. Verify errors logged.
Shawn McCarney371e2442021-05-14 14:18:07 -0500323 {
Shawn McCarney2ee44942021-09-09 17:58:14 -0500324 // Create mock services. Set expectations via lambda.
325 MockServices services{};
326 setExpectations(services);
327
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500328 for (int i = 1; i <= 10; ++i)
Shawn McCarney2ee44942021-09-09 17:58:14 -0500329 {
330 device.monitorSensors(services, *system, *chassis);
331 device.detectPhaseFaults(services, *system, *chassis);
332 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500333 }
334
335 // Clear error history
Shawn McCarney2874e902021-09-09 10:03:59 -0500336 device.clearErrorHistory();
Shawn McCarney371e2442021-05-14 14:18:07 -0500337
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500338 // Monitor sensors and detect phase faults 10 more times. Verify errors
Shawn McCarney2ee44942021-09-09 17:58:14 -0500339 // logged again.
Shawn McCarney371e2442021-05-14 14:18:07 -0500340 {
Shawn McCarney2ee44942021-09-09 17:58:14 -0500341 // Create mock services. Set expectations via lambda.
342 MockServices services{};
343 setExpectations(services);
344
Shawn McCarneyfa2734d2022-03-30 21:16:40 -0500345 for (int i = 1; i <= 10; ++i)
Shawn McCarney2ee44942021-09-09 17:58:14 -0500346 {
347 device.monitorSensors(services, *system, *chassis);
348 device.detectPhaseFaults(services, *system, *chassis);
349 }
Shawn McCarney371e2442021-05-14 14:18:07 -0500350 }
351}
352
Shawn McCarney2874e902021-09-09 10:03:59 -0500353TEST_F(DeviceTests, Close)
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500354{
355 // Test where works: I2C interface is not open
356 {
357 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500358 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500359 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
360 EXPECT_CALL(*i2cInterface, close).Times(0);
361
Bob Kingd692d6d2020-09-14 13:42:57 +0800362 // Create mock services. No logError should occur.
363 MockServices services{};
364 MockJournal& journal = services.getMockJournal();
365 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
366 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
367 .Times(0);
368
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500369 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500370 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500371
372 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800373 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500374 }
375
376 // Test where works: I2C interface is open
377 {
378 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500379 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500380 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
381 EXPECT_CALL(*i2cInterface, close).Times(1);
382
Bob Kingd692d6d2020-09-14 13:42:57 +0800383 // Create mock services. No logError should occur.
384 MockServices services{};
385 MockJournal& journal = services.getMockJournal();
386 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
387 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
388 .Times(0);
389
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500390 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500391 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500392
393 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800394 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500395 }
396
397 // Test where fails: closing I2C interface fails
398 {
399 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500400 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500401 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
402 EXPECT_CALL(*i2cInterface, close)
403 .Times(1)
404 .WillOnce(Throw(
405 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
406
Shawn McCarney81a2f902021-03-23 21:41:34 -0500407 // Create mock services. Expect logError() and logI2CError() to be
408 // called.
Bob Kingd692d6d2020-09-14 13:42:57 +0800409 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500410 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob Kingd692d6d2020-09-14 13:42:57 +0800411 MockJournal& journal = services.getMockJournal();
412 std::vector<std::string> expectedErrMessagesException{
413 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
414 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
415 .Times(1);
416 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500417 EXPECT_CALL(errorLogging,
418 logI2CError(Entry::Level::Notice, Ref(journal),
419 "/dev/i2c-1", 0x70, 0))
420 .Times(1);
Bob Kingd692d6d2020-09-14 13:42:57 +0800421
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500422 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500423 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500424
425 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800426 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500427 }
428}
429
Shawn McCarney2874e902021-09-09 10:03:59 -0500430TEST_F(DeviceTests, Configure)
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500431{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600432 // Test where device is not present
433 {
434 // Create mock services. No logging should occur.
435 MockServices services{};
436 MockJournal& journal = services.getMockJournal();
437 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
438 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
439
440 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500441 std::unique_ptr<PresenceDetection> presenceDetection{};
442 {
443 auto action = std::make_unique<MockAction>();
444 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
445 std::vector<std::unique_ptr<Action>> actions{};
446 actions.emplace_back(std::move(action));
447 presenceDetection =
448 std::make_unique<PresenceDetection>(std::move(actions));
449 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600450
451 // Create Configuration. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500452 std::unique_ptr<Configuration> configuration{};
453 {
454 std::optional<double> volts{};
455 auto action = std::make_unique<MockAction>();
456 EXPECT_CALL(*action, execute).Times(0);
457 std::vector<std::unique_ptr<Action>> actions{};
458 actions.emplace_back(std::move(action));
459 configuration =
460 std::make_unique<Configuration>(volts, std::move(actions));
461 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600462
463 // Create Device
464 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500465 Device device{"reg2",
466 true,
467 deviceInvPath,
468 std::move(i2cInterface),
469 std::move(presenceDetection),
470 std::move(configuration)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600471
472 // Call configure(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500473 device.configure(services, *system, *chassis);
Shawn McCarney48033bf2021-01-27 17:56:49 -0600474 }
475
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500476 // Test where Configuration and Rails were not specified in constructor
477 {
Bob King5cfe5102020-07-30 16:26:18 +0800478 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800479 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800480 MockJournal& journal = services.getMockJournal();
481 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
482 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800483
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500484 // Create Device
485 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500486 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500487
Bob King5cfe5102020-07-30 16:26:18 +0800488 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500489 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500490 }
491
492 // Test where Configuration and Rails were specified in constructor
493 {
494 std::vector<std::unique_ptr<Rail>> rails{};
495
Bob King5cfe5102020-07-30 16:26:18 +0800496 // Create mock services. Expect logDebug() to be called.
497 // For the Device and both Rails, should execute the Configuration
498 // and log a debug message.
499 MockServices services{};
500 MockJournal& journal = services.getMockJournal();
Shawn McCarney2874e902021-09-09 10:03:59 -0500501 EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
Bob King5cfe5102020-07-30 16:26:18 +0800502 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
503 .Times(1);
504 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
505 .Times(1);
506 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
507
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500508 // Create Rail vdd0
509 {
510 // Create Configuration for Rail
511 std::optional<double> volts{1.3};
Shawn McCarney2874e902021-09-09 10:03:59 -0500512 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500513 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
514 std::vector<std::unique_ptr<Action>> actions{};
515 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500516 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500517 std::make_unique<Configuration>(volts, std::move(actions));
518
519 // Create Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500520 auto rail =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500521 std::make_unique<Rail>("vdd0", std::move(configuration));
522 rails.emplace_back(std::move(rail));
523 }
524
525 // Create Rail vio0
526 {
527 // Create Configuration for Rail
528 std::optional<double> volts{3.2};
Shawn McCarney2874e902021-09-09 10:03:59 -0500529 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500530 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
531 std::vector<std::unique_ptr<Action>> actions{};
532 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500533 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500534 std::make_unique<Configuration>(volts, std::move(actions));
535
536 // Create Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500537 auto rail =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500538 std::make_unique<Rail>("vio0", std::move(configuration));
539 rails.emplace_back(std::move(rail));
540 }
541
542 // Create Configuration for Device
543 std::optional<double> volts{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500544 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500545 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
546 std::vector<std::unique_ptr<Action>> actions{};
547 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500548 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500549 std::make_unique<Configuration>(volts, std::move(actions));
550
551 // Create Device
552 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
553 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney32252592021-09-08 15:29:36 -0500554 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500555 Device device{"reg2",
556 true,
557 deviceInvPath,
558 std::move(i2cInterface),
559 std::move(presenceDetection),
560 std::move(configuration),
561 std::move(phaseFaultDetection),
562 std::move(rails)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500563
Bob King5cfe5102020-07-30 16:26:18 +0800564 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500565 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500566 }
567}
568
Shawn McCarney1fd0b142021-09-09 10:04:22 -0500569TEST_F(DeviceTests, DetectPhaseFaults)
570{
571 // Test where device is not present
572 {
573 // Create mock services. No errors should be logged.
574 MockServices services{};
575 MockJournal& journal = services.getMockJournal();
576 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
577 MockErrorLogging& errorLogging = services.getMockErrorLogging();
578 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
579
580 // Create PresenceDetection. Indicates device is not present.
581 std::unique_ptr<PresenceDetection> presenceDetection{};
582 {
583 auto action = std::make_unique<MockAction>();
584 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
585 std::vector<std::unique_ptr<Action>> actions{};
586 actions.emplace_back(std::move(action));
587 presenceDetection =
588 std::make_unique<PresenceDetection>(std::move(actions));
589 }
590
591 // Create PhaseFaultDetection. Action inside it should not be executed.
592 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
593 {
594 auto action = std::make_unique<MockAction>();
595 EXPECT_CALL(*action, execute).Times(0);
596 std::vector<std::unique_ptr<Action>> actions{};
597 actions.emplace_back(std::move(action));
598 phaseFaultDetection =
599 std::make_unique<PhaseFaultDetection>(std::move(actions));
600 }
601
602 // Create Device
603 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
604 std::unique_ptr<Configuration> configuration{};
605 Device device{"reg2",
606 true,
607 deviceInvPath,
608 std::move(i2cInterface),
609 std::move(presenceDetection),
610 std::move(configuration),
611 std::move(phaseFaultDetection)};
612
613 // Call detectPhaseFaults() 5 times. Should do nothing.
614 for (int i = 1; i <= 5; ++i)
615 {
616 device.detectPhaseFaults(services, *system, *chassis);
617 }
618 }
619
620 // Test where PhaseFaultDetection was not specified in constructor
621 {
622 // Create mock services. No errors should be logged.
623 MockServices services{};
624 MockJournal& journal = services.getMockJournal();
625 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
626 MockErrorLogging& errorLogging = services.getMockErrorLogging();
627 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
628
629 // Create Device
630 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
631 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
632
633 // Call detectPhaseFaults() 5 times. Should do nothing.
634 for (int i = 1; i <= 5; ++i)
635 {
636 device.detectPhaseFaults(services, *system, *chassis);
637 }
638 }
639
640 // Test where PhaseFaultDetection was specified in constructor
641 {
642 // Create mock services with the following expectations:
643 // - 2 error messages in journal for N phase fault detected
644 // - 1 N phase fault error logged
645 MockServices services{};
646 MockJournal& journal = services.getMockJournal();
647 EXPECT_CALL(
648 journal,
649 logError("n phase fault detected in regulator reg2: count=1"))
650 .Times(1);
651 EXPECT_CALL(
652 journal,
653 logError("n phase fault detected in regulator reg2: count=2"))
654 .Times(1);
655 MockErrorLogging& errorLogging = services.getMockErrorLogging();
656 EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
657
658 // Create PhaseFaultDetection
659 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
660 std::vector<std::unique_ptr<Action>> actions{};
661 actions.push_back(std::move(action));
662 auto phaseFaultDetection =
663 std::make_unique<PhaseFaultDetection>(std::move(actions));
664
665 // Create Device
666 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
667 std::unique_ptr<PresenceDetection> presenceDetection{};
668 std::unique_ptr<Configuration> configuration{};
669 Device device{"reg2",
670 true,
671 deviceInvPath,
672 std::move(i2cInterface),
673 std::move(presenceDetection),
674 std::move(configuration),
675 std::move(phaseFaultDetection)};
676
677 // Call detectPhaseFaults() 5 times
678 for (int i = 1; i <= 5; ++i)
679 {
680 device.detectPhaseFaults(services, *system, *chassis);
681 }
682 }
683}
684
Shawn McCarney2874e902021-09-09 10:03:59 -0500685TEST_F(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500686{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500687 // Test where Configuration was not specified in constructor
688 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500689 Device device{"vdd_reg", true, deviceInvPath,
690 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500691 EXPECT_EQ(device.getConfiguration(), nullptr);
692 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600693
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500694 // Test where Configuration was specified in constructor
695 {
696 std::unique_ptr<PresenceDetection> presenceDetection{};
697
698 // Create Configuration
699 std::optional<double> volts{3.2};
700 std::vector<std::unique_ptr<Action>> actions{};
701 actions.push_back(std::make_unique<MockAction>());
702 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500703 auto configuration =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500704 std::make_unique<Configuration>(volts, std::move(actions));
705
706 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500707 Device device{"vdd_reg",
708 true,
709 deviceInvPath,
710 std::move(createI2CInterface()),
711 std::move(presenceDetection),
712 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500713 EXPECT_NE(device.getConfiguration(), nullptr);
714 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
715 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
716 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
717 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600718}
719
Shawn McCarney2874e902021-09-09 10:03:59 -0500720TEST_F(DeviceTests, GetFRU)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600721{
Shawn McCarney2874e902021-09-09 10:03:59 -0500722 Device device{"vdd_reg", true, deviceInvPath,
723 std::move(createI2CInterface())};
724 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600725}
726
Shawn McCarney2874e902021-09-09 10:03:59 -0500727TEST_F(DeviceTests, GetI2CInterface)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600728{
729 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
730 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Shawn McCarney2874e902021-09-09 10:03:59 -0500731 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600732 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500733}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500734
Shawn McCarney2874e902021-09-09 10:03:59 -0500735TEST_F(DeviceTests, GetID)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500736{
Shawn McCarney2874e902021-09-09 10:03:59 -0500737 Device device{"vdd_reg", false, deviceInvPath,
738 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500739 EXPECT_EQ(device.getID(), "vdd_reg");
740}
741
Shawn McCarney2874e902021-09-09 10:03:59 -0500742TEST_F(DeviceTests, GetPhaseFaultDetection)
Shawn McCarney32252592021-09-08 15:29:36 -0500743{
744 // Test where PhaseFaultDetection was not specified in constructor
745 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500746 Device device{"vdd_reg", true, deviceInvPath,
747 std::move(createI2CInterface())};
Shawn McCarney32252592021-09-08 15:29:36 -0500748 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
749 }
750
751 // Test where PhaseFaultDetection was specified in constructor
752 {
753 // Create PhaseFaultDetection
754 std::vector<std::unique_ptr<Action>> actions{};
755 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500756 auto phaseFaultDetection =
Shawn McCarney32252592021-09-08 15:29:36 -0500757 std::make_unique<PhaseFaultDetection>(std::move(actions));
758
759 // Create Device
760 std::unique_ptr<PresenceDetection> presenceDetection{};
761 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500762 Device device{"vdd_reg",
763 false,
764 deviceInvPath,
765 std::move(createI2CInterface()),
766 std::move(presenceDetection),
767 std::move(configuration),
768 std::move(phaseFaultDetection)};
Shawn McCarney32252592021-09-08 15:29:36 -0500769 EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
770 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
771 }
772}
773
Shawn McCarney2874e902021-09-09 10:03:59 -0500774TEST_F(DeviceTests, GetPresenceDetection)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500775{
776 // Test where PresenceDetection was not specified in constructor
777 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500778 Device device{"vdd_reg", true, deviceInvPath,
779 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500780 EXPECT_EQ(device.getPresenceDetection(), nullptr);
781 }
782
783 // Test where PresenceDetection was specified in constructor
784 {
785 // Create PresenceDetection
786 std::vector<std::unique_ptr<Action>> actions{};
787 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500788 auto presenceDetection =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500789 std::make_unique<PresenceDetection>(std::move(actions));
790
791 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500792 Device device{"vdd_reg", false, deviceInvPath,
793 std::move(createI2CInterface()),
794 std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500795 EXPECT_NE(device.getPresenceDetection(), nullptr);
796 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
797 }
798}
799
Shawn McCarney2874e902021-09-09 10:03:59 -0500800TEST_F(DeviceTests, GetRails)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500801{
802 // Test where no rails were specified in constructor
803 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500804 Device device{"vdd_reg", true, deviceInvPath,
805 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500806 EXPECT_EQ(device.getRails().size(), 0);
807 }
808
809 // Test where rails were specified in constructor
810 {
811 std::unique_ptr<PresenceDetection> presenceDetection{};
812 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500813 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500814
815 // Create vector of Rail objects
816 std::vector<std::unique_ptr<Rail>> rails{};
817 rails.push_back(std::make_unique<Rail>("vdd0"));
818 rails.push_back(std::make_unique<Rail>("vdd1"));
819
820 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500821 Device device{"vdd_reg",
822 false,
823 deviceInvPath,
824 std::move(createI2CInterface()),
825 std::move(presenceDetection),
826 std::move(configuration),
827 std::move(phaseFaultDetection),
828 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500829 EXPECT_EQ(device.getRails().size(), 2);
830 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
831 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
832 }
833}
834
Shawn McCarney2874e902021-09-09 10:03:59 -0500835TEST_F(DeviceTests, IsPresent)
Shawn McCarney48033bf2021-01-27 17:56:49 -0600836{
837 // Test where PresenceDetection not specified in constructor
838 {
839 // Create Device
840 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500841 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600842
843 // Create MockServices
844 MockServices services{};
845
846 // Since no PresenceDetection defined, isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500847 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600848 }
849
850 // Test where PresenceDetection was specified in constructor: Is present
851 {
852 // Create PresenceDetection. Indicates device is present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500853 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600854 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
855 std::vector<std::unique_ptr<Action>> actions{};
856 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500857 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600858 std::make_unique<PresenceDetection>(std::move(actions));
859
860 // Create Device
861 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500862 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
863 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600864
865 // Create MockServices
866 MockServices services{};
867
868 // PresenceDetection::execute() and isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500869 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600870 }
871
872 // Test where PresenceDetection was specified in constructor: Is not present
873 {
874 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500875 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600876 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
877 std::vector<std::unique_ptr<Action>> actions{};
878 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500879 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600880 std::make_unique<PresenceDetection>(std::move(actions));
881
882 // Create Device
883 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500884 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
885 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600886
887 // Create MockServices
888 MockServices services{};
889
890 // PresenceDetection::execute() and isPresent() should return false
Shawn McCarney2874e902021-09-09 10:03:59 -0500891 EXPECT_FALSE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600892 }
893}
894
Shawn McCarney2874e902021-09-09 10:03:59 -0500895TEST_F(DeviceTests, IsRegulator)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500896{
Shawn McCarney2874e902021-09-09 10:03:59 -0500897 Device device{"vdd_reg", false, deviceInvPath,
898 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500899 EXPECT_EQ(device.isRegulator(), false);
900}
Bob King8e1cd0b2020-07-08 13:30:27 +0800901
Shawn McCarney2874e902021-09-09 10:03:59 -0500902TEST_F(DeviceTests, MonitorSensors)
Bob King8e1cd0b2020-07-08 13:30:27 +0800903{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600904 // Test where device is not present
Bob King8e1cd0b2020-07-08 13:30:27 +0800905 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500906 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800907 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500908 MockSensors& sensors = services.getMockSensors();
909 EXPECT_CALL(sensors, startRail).Times(0);
910 EXPECT_CALL(sensors, setValue).Times(0);
911 EXPECT_CALL(sensors, endRail).Times(0);
Bob King8a552922020-08-05 17:02:31 +0800912
Shawn McCarney17bac892021-05-08 07:55:52 -0500913 // Create SensorMonitoring. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500914 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
915 {
916 auto action = std::make_unique<MockAction>();
917 EXPECT_CALL(*action, execute).Times(0);
918 std::vector<std::unique_ptr<Action>> actions{};
919 actions.emplace_back(std::move(action));
920 sensorMonitoring =
921 std::make_unique<SensorMonitoring>(std::move(actions));
922 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800923
924 // Create Rail
925 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500926 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
927 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500928
929 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500930 std::unique_ptr<PresenceDetection> presenceDetection{};
931 {
932 auto action = std::make_unique<MockAction>();
933 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
934 std::vector<std::unique_ptr<Action>> actions{};
935 actions.emplace_back(std::move(action));
936 presenceDetection =
937 std::make_unique<PresenceDetection>(std::move(actions));
938 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800939
940 // Create Device
Shawn McCarney17bac892021-05-08 07:55:52 -0500941 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Bob King8e1cd0b2020-07-08 13:30:27 +0800942 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500943 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500944 std::vector<std::unique_ptr<Rail>> rails{};
945 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500946 Device device{"reg2",
947 true,
948 deviceInvPath,
949 std::move(i2cInterface),
950 std::move(presenceDetection),
951 std::move(deviceConfiguration),
952 std::move(phaseFaultDetection),
953 std::move(rails)};
Bob King8e1cd0b2020-07-08 13:30:27 +0800954
Shawn McCarney17bac892021-05-08 07:55:52 -0500955 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500956 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500957 }
958
959 // Test where Rails were not specified in constructor
960 {
961 // Create mock services. No Sensors methods should be called.
962 MockServices services{};
963 MockSensors& sensors = services.getMockSensors();
964 EXPECT_CALL(sensors, startRail).Times(0);
965 EXPECT_CALL(sensors, setValue).Times(0);
966 EXPECT_CALL(sensors, endRail).Times(0);
967
968 // Create Device
969 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500970 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney17bac892021-05-08 07:55:52 -0500971
972 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500973 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500974 }
975
976 // Test where Rails were specified in constructor
977 {
978 // Create mock services. Set Sensors service expectations.
979 MockServices services{};
980 MockSensors& sensors = services.getMockSensors();
Shawn McCarney2874e902021-09-09 10:03:59 -0500981 EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500982 .Times(1);
Shawn McCarney2874e902021-09-09 10:03:59 -0500983 EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500984 .Times(1);
985 EXPECT_CALL(sensors, setValue).Times(0);
986 EXPECT_CALL(sensors, endRail(false)).Times(2);
987
988 std::vector<std::unique_ptr<Rail>> rails{};
989
990 // Create Rail vdd0
991 {
992 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500993 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500994 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
995 std::vector<std::unique_ptr<Action>> actions{};
996 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500997 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500998 std::make_unique<SensorMonitoring>(std::move(actions));
999
1000 // Create Rail
1001 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -05001002 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
1003 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -05001004 rails.emplace_back(std::move(rail));
1005 }
1006
1007 // Create Rail vio0
1008 {
1009 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -05001010 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -05001011 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
1012 std::vector<std::unique_ptr<Action>> actions{};
1013 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -05001014 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -05001015 std::make_unique<SensorMonitoring>(std::move(actions));
1016
1017 // Create Rail
1018 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -05001019 auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
1020 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -05001021 rails.emplace_back(std::move(rail));
1022 }
1023
1024 // Create Device that contains Rails
1025 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
1026 std::unique_ptr<PresenceDetection> presenceDetection{};
1027 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -05001028 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -05001029 Device device{"reg2",
1030 true,
1031 deviceInvPath,
1032 std::move(i2cInterface),
1033 std::move(presenceDetection),
1034 std::move(configuration),
1035 std::move(phaseFaultDetection),
1036 std::move(rails)};
Shawn McCarney17bac892021-05-08 07:55:52 -05001037
1038 // Call monitorSensors(). Should monitor sensors in both rails.
Shawn McCarney2874e902021-09-09 10:03:59 -05001039 device.monitorSensors(services, *system, *chassis);
Bob King8e1cd0b2020-07-08 13:30:27 +08001040 }
1041}