xref: /openbmc/phosphor-power/phosphor-regulators/test/device_tests.cpp (revision f54021972b91be5058b50e9046bb0dd5a3b22a80)
1a2461b34SShawn McCarney /**
2a2461b34SShawn McCarney  * Copyright © 2019 IBM Corporation
3a2461b34SShawn McCarney  *
4a2461b34SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5a2461b34SShawn McCarney  * you may not use this file except in compliance with the License.
6a2461b34SShawn McCarney  * You may obtain a copy of the License at
7a2461b34SShawn McCarney  *
8a2461b34SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9a2461b34SShawn McCarney  *
10a2461b34SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11a2461b34SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12a2461b34SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2461b34SShawn McCarney  * See the License for the specific language governing permissions and
14a2461b34SShawn McCarney  * limitations under the License.
15a2461b34SShawn McCarney  */
160b1a0e7aSShawn McCarney #include "action.hpp"
17eb7bec4aSShawn McCarney #include "chassis.hpp"
180b1a0e7aSShawn McCarney #include "configuration.hpp"
19a2461b34SShawn McCarney #include "device.hpp"
20afb7fc3fSShawn McCarney #include "i2c_interface.hpp"
21db0b833cSShawn McCarney #include "id_map.hpp"
221fd0b145SShawn McCarney #include "log_phase_fault_action.hpp"
230b1a0e7aSShawn McCarney #include "mock_action.hpp"
2481a2f90bSShawn McCarney #include "mock_error_logging.hpp"
25eb7bec4aSShawn McCarney #include "mock_journal.hpp"
2617bac89eSShawn McCarney #include "mock_sensors.hpp"
2723243f84SBob King #include "mock_services.hpp"
28b4d18a45SShawn McCarney #include "mocked_i2c_interface.hpp"
291fd0b145SShawn McCarney #include "phase_fault.hpp"
3032252599SShawn McCarney #include "phase_fault_detection.hpp"
310b1a0e7aSShawn McCarney #include "presence_detection.hpp"
320b1a0e7aSShawn McCarney #include "rail.hpp"
33eb7bec4aSShawn McCarney #include "rule.hpp"
3417bac89eSShawn McCarney #include "sensor_monitoring.hpp"
352f9e14f6SShawn McCarney #include "sensors.hpp"
36eb7bec4aSShawn McCarney #include "system.hpp"
37371e244aSShawn McCarney #include "test_sdbus_error.hpp"
388a3afd70SShawn McCarney #include "test_utils.hpp"
39afb7fc3fSShawn McCarney 
40afb7fc3fSShawn McCarney #include <memory>
410b1a0e7aSShawn McCarney #include <optional>
42525e20c9SShawn McCarney #include <string>
43afb7fc3fSShawn McCarney #include <utility>
440b1a0e7aSShawn McCarney #include <vector>
45a2461b34SShawn McCarney 
46eb7bec4aSShawn McCarney #include <gmock/gmock.h>
47a2461b34SShawn McCarney #include <gtest/gtest.h>
48a2461b34SShawn McCarney 
49a2461b34SShawn McCarney using namespace phosphor::power::regulators;
508a3afd70SShawn McCarney using namespace phosphor::power::regulators::test_utils;
51afb7fc3fSShawn McCarney 
528e1cd0b6SBob King using ::testing::A;
5381a2f90bSShawn McCarney using ::testing::Ref;
54eb7bec4aSShawn McCarney using ::testing::Return;
55b4d18a45SShawn McCarney using ::testing::Throw;
568e1cd0b6SBob King using ::testing::TypedEq;
57eb7bec4aSShawn McCarney 
582874e902SShawn McCarney class DeviceTests : public ::testing::Test
592874e902SShawn McCarney {
602874e902SShawn McCarney   public:
612874e902SShawn McCarney     /**
622874e902SShawn McCarney      * Constructor.
632874e902SShawn McCarney      *
642874e902SShawn McCarney      * Creates the Chassis and System objects needed for calling some Device
652874e902SShawn McCarney      * methods.
662874e902SShawn McCarney      */
DeviceTests()672874e902SShawn McCarney     DeviceTests() : ::testing::Test{}
682874e902SShawn McCarney     {
692874e902SShawn McCarney         // Create Chassis
702874e902SShawn McCarney         auto chassis = std::make_unique<Chassis>(1, chassisInvPath);
712874e902SShawn McCarney         this->chassis = chassis.get();
722874e902SShawn McCarney 
732874e902SShawn McCarney         // Create System
742874e902SShawn McCarney         std::vector<std::unique_ptr<Rule>> rules{};
752874e902SShawn McCarney         std::vector<std::unique_ptr<Chassis>> chassisVec{};
762874e902SShawn McCarney         chassisVec.emplace_back(std::move(chassis));
77*f5402197SPatrick Williams         this->system =
78*f5402197SPatrick Williams             std::make_unique<System>(std::move(rules), std::move(chassisVec));
792874e902SShawn McCarney     }
802874e902SShawn McCarney 
812874e902SShawn McCarney   protected:
822874e902SShawn McCarney     const std::string deviceInvPath{
832874e902SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"};
842874e902SShawn McCarney     const std::string chassisInvPath{
85cb3f6a63SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis"};
86cb3f6a63SShawn McCarney 
872874e902SShawn McCarney     // Note: This pointer does NOT need to be explicitly deleted.  The Chassis
882874e902SShawn McCarney     // object is owned by the System object and will be automatically deleted.
892874e902SShawn McCarney     Chassis* chassis{nullptr};
902874e902SShawn McCarney 
912874e902SShawn McCarney     std::unique_ptr<System> system{};
922874e902SShawn McCarney };
932874e902SShawn McCarney 
TEST_F(DeviceTests,Constructor)942874e902SShawn McCarney TEST_F(DeviceTests, Constructor)
95a2461b34SShawn McCarney {
960b1a0e7aSShawn McCarney     // Test where only required parameters are specified
970b1a0e7aSShawn McCarney     {
98afb7fc3fSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
99afb7fc3fSShawn McCarney         i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
1002874e902SShawn McCarney         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
101afb7fc3fSShawn McCarney         EXPECT_EQ(device.getID(), "vdd_reg");
102afb7fc3fSShawn McCarney         EXPECT_EQ(device.isRegulator(), true);
1032874e902SShawn McCarney         EXPECT_EQ(device.getFRU(), deviceInvPath);
104afb7fc3fSShawn McCarney         EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
1050b1a0e7aSShawn McCarney         EXPECT_EQ(device.getPresenceDetection(), nullptr);
1060b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration(), nullptr);
10732252599SShawn McCarney         EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
1080b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails().size(), 0);
109a2461b34SShawn McCarney     }
110a2461b34SShawn McCarney 
1110b1a0e7aSShawn McCarney     // Test where all parameters are specified
112a2461b34SShawn McCarney     {
1130b1a0e7aSShawn McCarney         // Create I2CInterface
1140b1a0e7aSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
1150b1a0e7aSShawn McCarney         i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
1160b1a0e7aSShawn McCarney 
1170b1a0e7aSShawn McCarney         // Create PresenceDetection
1180b1a0e7aSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
1190b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
1202874e902SShawn McCarney         auto presenceDetection =
1210b1a0e7aSShawn McCarney             std::make_unique<PresenceDetection>(std::move(actions));
1220b1a0e7aSShawn McCarney 
1230b1a0e7aSShawn McCarney         // Create Configuration
1240b1a0e7aSShawn McCarney         std::optional<double> volts{};
1250b1a0e7aSShawn McCarney         actions.clear();
1260b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
1270b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
1282874e902SShawn McCarney         auto configuration =
1290b1a0e7aSShawn McCarney             std::make_unique<Configuration>(volts, std::move(actions));
1300b1a0e7aSShawn McCarney 
13132252599SShawn McCarney         // Create PhaseFaultDetection
13232252599SShawn McCarney         actions.clear();
13332252599SShawn McCarney         actions.push_back(std::make_unique<MockAction>());
13432252599SShawn McCarney         actions.push_back(std::make_unique<MockAction>());
13532252599SShawn McCarney         actions.push_back(std::make_unique<MockAction>());
1362874e902SShawn McCarney         auto phaseFaultDetection =
13732252599SShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
13832252599SShawn McCarney 
1390b1a0e7aSShawn McCarney         // Create vector of Rail objects
1400b1a0e7aSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
1410b1a0e7aSShawn McCarney         rails.push_back(std::make_unique<Rail>("vdd0"));
1420b1a0e7aSShawn McCarney         rails.push_back(std::make_unique<Rail>("vdd1"));
1430b1a0e7aSShawn McCarney 
1440b1a0e7aSShawn McCarney         // Create Device
1452874e902SShawn McCarney         Device device{"vdd_reg",
1460b1a0e7aSShawn McCarney                       false,
1472874e902SShawn McCarney                       deviceInvPath,
1480b1a0e7aSShawn McCarney                       std::move(i2cInterface),
1490b1a0e7aSShawn McCarney                       std::move(presenceDetection),
1500b1a0e7aSShawn McCarney                       std::move(configuration),
15132252599SShawn McCarney                       std::move(phaseFaultDetection),
1520b1a0e7aSShawn McCarney                       std::move(rails)};
153afb7fc3fSShawn McCarney         EXPECT_EQ(device.getID(), "vdd_reg");
1540b1a0e7aSShawn McCarney         EXPECT_EQ(device.isRegulator(), false);
1552874e902SShawn McCarney         EXPECT_EQ(device.getFRU(), deviceInvPath);
1560b1a0e7aSShawn McCarney         EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
1570b1a0e7aSShawn McCarney         EXPECT_NE(device.getPresenceDetection(), nullptr);
1580b1a0e7aSShawn McCarney         EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
1590b1a0e7aSShawn McCarney         EXPECT_NE(device.getConfiguration(), nullptr);
1600b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
1610b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
16232252599SShawn McCarney         EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
16332252599SShawn McCarney         EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 3);
1640b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails().size(), 2);
1650b1a0e7aSShawn McCarney     }
166afb7fc3fSShawn McCarney }
167afb7fc3fSShawn McCarney 
TEST_F(DeviceTests,AddToIDMap)1682874e902SShawn McCarney TEST_F(DeviceTests, AddToIDMap)
169db0b833cSShawn McCarney {
170db0b833cSShawn McCarney     std::unique_ptr<PresenceDetection> presenceDetection{};
171db0b833cSShawn McCarney     std::unique_ptr<Configuration> configuration{};
17232252599SShawn McCarney     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
173db0b833cSShawn McCarney 
174db0b833cSShawn McCarney     // Create vector of Rail objects
175db0b833cSShawn McCarney     std::vector<std::unique_ptr<Rail>> rails{};
176db0b833cSShawn McCarney     rails.push_back(std::make_unique<Rail>("vdd0"));
177db0b833cSShawn McCarney     rails.push_back(std::make_unique<Rail>("vdd1"));
178db0b833cSShawn McCarney 
179db0b833cSShawn McCarney     // Create Device
1802874e902SShawn McCarney     Device device{"vdd_reg",
181db0b833cSShawn McCarney                   false,
1822874e902SShawn McCarney                   deviceInvPath,
18341a6b9f3SPatrick Williams                   createI2CInterface(),
184db0b833cSShawn McCarney                   std::move(presenceDetection),
185db0b833cSShawn McCarney                   std::move(configuration),
18632252599SShawn McCarney                   std::move(phaseFaultDetection),
187db0b833cSShawn McCarney                   std::move(rails)};
188db0b833cSShawn McCarney 
189db0b833cSShawn McCarney     // Add Device and Rail objects to an IDMap
190db0b833cSShawn McCarney     IDMap idMap{};
191db0b833cSShawn McCarney     device.addToIDMap(idMap);
192db0b833cSShawn McCarney 
193db0b833cSShawn McCarney     // Verify Device is in the IDMap
194db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
195db0b833cSShawn McCarney     EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
196db0b833cSShawn McCarney 
197db0b833cSShawn McCarney     // Verify all Rails are in the IDMap
198db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("vdd0"));
199db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("vdd1"));
200db0b833cSShawn McCarney     EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
201db0b833cSShawn McCarney }
202db0b833cSShawn McCarney 
TEST_F(DeviceTests,ClearCache)2032874e902SShawn McCarney TEST_F(DeviceTests, ClearCache)
2049bd94d36SShawn McCarney {
2059bd94d36SShawn McCarney     // Test where Device does not contain a PresenceDetection object
2069bd94d36SShawn McCarney     try
2079bd94d36SShawn McCarney     {
20841a6b9f3SPatrick Williams         Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
2099bd94d36SShawn McCarney         device.clearCache();
2109bd94d36SShawn McCarney     }
2119bd94d36SShawn McCarney     catch (...)
2129bd94d36SShawn McCarney     {
2139bd94d36SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
2149bd94d36SShawn McCarney     }
2159bd94d36SShawn McCarney 
2169bd94d36SShawn McCarney     // Test where Device contains a PresenceDetection object
2179bd94d36SShawn McCarney     {
2189bd94d36SShawn McCarney         // Create PresenceDetection
2199bd94d36SShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
2202874e902SShawn McCarney         auto presenceDetection =
2219bd94d36SShawn McCarney             std::make_unique<PresenceDetection>(std::move(actions));
2229bd94d36SShawn McCarney         PresenceDetection* presenceDetectionPtr = presenceDetection.get();
2239bd94d36SShawn McCarney 
2249bd94d36SShawn McCarney         // Create Device
2259bd94d36SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
2262874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
2272874e902SShawn McCarney                       std::move(presenceDetection)};
2289bd94d36SShawn McCarney 
2299bd94d36SShawn McCarney         // Cache presence value in PresenceDetection
2309bd94d36SShawn McCarney         MockServices services{};
2312874e902SShawn McCarney         presenceDetectionPtr->execute(services, *system, *chassis, device);
2329bd94d36SShawn McCarney         EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
2339bd94d36SShawn McCarney 
2349bd94d36SShawn McCarney         // Clear cached data in Device
2352874e902SShawn McCarney         device.clearCache();
2369bd94d36SShawn McCarney 
2379bd94d36SShawn McCarney         // Verify presence value no longer cached in PresenceDetection
2389bd94d36SShawn McCarney         EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
2399bd94d36SShawn McCarney     }
2409bd94d36SShawn McCarney }
2419bd94d36SShawn McCarney 
TEST_F(DeviceTests,ClearErrorHistory)2422874e902SShawn McCarney TEST_F(DeviceTests, ClearErrorHistory)
243371e244aSShawn McCarney {
244371e244aSShawn McCarney     // Create SensorMonitoring.  Will fail with a DBus exception.
2452ee4494cSShawn McCarney     std::unique_ptr<SensorMonitoring> sensorMonitoring{};
2462ee4494cSShawn McCarney     {
2472874e902SShawn McCarney         auto action = std::make_unique<MockAction>();
248371e244aSShawn McCarney         EXPECT_CALL(*action, execute)
2492ee4494cSShawn McCarney             .WillRepeatedly(Throw(TestSDBusError{"DBus Error"}));
250371e244aSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
251371e244aSShawn McCarney         actions.emplace_back(std::move(action));
2522ee4494cSShawn McCarney         sensorMonitoring =
253371e244aSShawn McCarney             std::make_unique<SensorMonitoring>(std::move(actions));
2542ee4494cSShawn McCarney     }
255371e244aSShawn McCarney 
256371e244aSShawn McCarney     // Create Rail
257371e244aSShawn McCarney     std::unique_ptr<Configuration> configuration{};
2582ee4494cSShawn McCarney     auto rail = std::make_unique<Rail>("vdd", std::move(configuration),
2592874e902SShawn McCarney                                        std::move(sensorMonitoring));
260371e244aSShawn McCarney 
2612ee4494cSShawn McCarney     // Create PhaseFaultDetection.  Will log an N phase fault.
2622ee4494cSShawn McCarney     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
2632ee4494cSShawn McCarney     {
2642ee4494cSShawn McCarney         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
2652ee4494cSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
2662ee4494cSShawn McCarney         actions.emplace_back(std::move(action));
2672ee4494cSShawn McCarney         phaseFaultDetection =
2682ee4494cSShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
2692ee4494cSShawn McCarney     }
2702ee4494cSShawn McCarney 
2712ee4494cSShawn McCarney     // Create Device
2722874e902SShawn McCarney     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
273371e244aSShawn McCarney     std::unique_ptr<PresenceDetection> presenceDetection{};
274371e244aSShawn McCarney     std::unique_ptr<Configuration> deviceConfiguration{};
275371e244aSShawn McCarney     std::vector<std::unique_ptr<Rail>> rails{};
276371e244aSShawn McCarney     rails.emplace_back(std::move(rail));
2772874e902SShawn McCarney     Device device{"reg2",
2782874e902SShawn McCarney                   true,
2792874e902SShawn McCarney                   deviceInvPath,
2802874e902SShawn McCarney                   std::move(i2cInterface),
2812874e902SShawn McCarney                   std::move(presenceDetection),
2822874e902SShawn McCarney                   std::move(deviceConfiguration),
2832874e902SShawn McCarney                   std::move(phaseFaultDetection),
2842874e902SShawn McCarney                   std::move(rails)};
285371e244aSShawn McCarney 
286fa2734d6SShawn McCarney     // Create lambda that sets MockServices expectations.  The lambda allows
287fa2734d6SShawn McCarney     // us to set expectations multiple times without duplicate code.
2882ee4494cSShawn McCarney     auto setExpectations = [](MockServices& services) {
2892ee4494cSShawn McCarney         // Set Journal service expectations:
290fa2734d6SShawn McCarney         // - 6 error messages for D-Bus errors
291fa2734d6SShawn McCarney         // - 6 error messages for inability to monitor sensors
2922ee4494cSShawn McCarney         // - 2 error messages for the N phase fault
293371e244aSShawn McCarney         MockJournal& journal = services.getMockJournal();
2942ee4494cSShawn McCarney         EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"}))
295fa2734d6SShawn McCarney             .Times(6);
2962ee4494cSShawn McCarney         EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd"))
297fa2734d6SShawn McCarney             .Times(6);
2982ee4494cSShawn McCarney         EXPECT_CALL(
2992ee4494cSShawn McCarney             journal,
3002ee4494cSShawn McCarney             logError("n phase fault detected in regulator reg2: count=1"))
3012ee4494cSShawn McCarney             .Times(1);
3022ee4494cSShawn McCarney         EXPECT_CALL(
3032ee4494cSShawn McCarney             journal,
3042ee4494cSShawn McCarney             logError("n phase fault detected in regulator reg2: count=2"))
3052ee4494cSShawn McCarney             .Times(1);
306371e244aSShawn McCarney 
3072ee4494cSShawn McCarney         // Set ErrorLogging service expectations:
3082ee4494cSShawn McCarney         // - D-Bus error should be logged once for the D-Bus exceptions
3092ee4494cSShawn McCarney         // - N phase fault error should be logged once
310371e244aSShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
3112ee4494cSShawn McCarney         EXPECT_CALL(errorLogging, logDBusError).Times(1);
3122ee4494cSShawn McCarney         EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
313371e244aSShawn McCarney 
3142ee4494cSShawn McCarney         // Set Sensors service expections:
315fa2734d6SShawn McCarney         // - startRail() and endRail() called 10 times
3162ee4494cSShawn McCarney         MockSensors& sensors = services.getMockSensors();
317fa2734d6SShawn McCarney         EXPECT_CALL(sensors, startRail).Times(10);
318fa2734d6SShawn McCarney         EXPECT_CALL(sensors, endRail).Times(10);
3192ee4494cSShawn McCarney     };
3202ee4494cSShawn McCarney 
321fa2734d6SShawn McCarney     // Monitor sensors and detect phase faults 10 times.  Verify errors logged.
3222ee4494cSShawn McCarney     {
3232ee4494cSShawn McCarney         // Create mock services.  Set expectations via lambda.
3242ee4494cSShawn McCarney         MockServices services{};
3252ee4494cSShawn McCarney         setExpectations(services);
3262ee4494cSShawn McCarney 
327fa2734d6SShawn McCarney         for (int i = 1; i <= 10; ++i)
328371e244aSShawn McCarney         {
3292874e902SShawn McCarney             device.monitorSensors(services, *system, *chassis);
3302ee4494cSShawn McCarney             device.detectPhaseFaults(services, *system, *chassis);
3312ee4494cSShawn McCarney         }
332371e244aSShawn McCarney     }
333371e244aSShawn McCarney 
334371e244aSShawn McCarney     // Clear error history
3352874e902SShawn McCarney     device.clearErrorHistory();
336371e244aSShawn McCarney 
337fa2734d6SShawn McCarney     // Monitor sensors and detect phase faults 10 more times.  Verify errors
3382ee4494cSShawn McCarney     // logged again.
3392ee4494cSShawn McCarney     {
3402ee4494cSShawn McCarney         // Create mock services.  Set expectations via lambda.
3412ee4494cSShawn McCarney         MockServices services{};
3422ee4494cSShawn McCarney         setExpectations(services);
3432ee4494cSShawn McCarney 
344fa2734d6SShawn McCarney         for (int i = 1; i <= 10; ++i)
345371e244aSShawn McCarney         {
3462874e902SShawn McCarney             device.monitorSensors(services, *system, *chassis);
3472ee4494cSShawn McCarney             device.detectPhaseFaults(services, *system, *chassis);
3482ee4494cSShawn McCarney         }
349371e244aSShawn McCarney     }
350371e244aSShawn McCarney }
351371e244aSShawn McCarney 
TEST_F(DeviceTests,Close)3522874e902SShawn McCarney TEST_F(DeviceTests, Close)
353b4d18a45SShawn McCarney {
354b4d18a45SShawn McCarney     // Test where works: I2C interface is not open
355b4d18a45SShawn McCarney     {
356b4d18a45SShawn McCarney         // Create mock I2CInterface
3572874e902SShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
358b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
359b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, close).Times(0);
360b4d18a45SShawn McCarney 
361d692d6dfSBob King         // Create mock services.  No logError should occur.
362d692d6dfSBob King         MockServices services{};
363d692d6dfSBob King         MockJournal& journal = services.getMockJournal();
364d692d6dfSBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
365d692d6dfSBob King         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
366d692d6dfSBob King             .Times(0);
367d692d6dfSBob King 
368b4d18a45SShawn McCarney         // Create Device
3692874e902SShawn McCarney         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
370b4d18a45SShawn McCarney 
371b4d18a45SShawn McCarney         // Close Device
372d692d6dfSBob King         device.close(services);
373b4d18a45SShawn McCarney     }
374b4d18a45SShawn McCarney 
375b4d18a45SShawn McCarney     // Test where works: I2C interface is open
376b4d18a45SShawn McCarney     {
377b4d18a45SShawn McCarney         // Create mock I2CInterface
3782874e902SShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
379b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
380b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, close).Times(1);
381b4d18a45SShawn McCarney 
382d692d6dfSBob King         // Create mock services.  No logError should occur.
383d692d6dfSBob King         MockServices services{};
384d692d6dfSBob King         MockJournal& journal = services.getMockJournal();
385d692d6dfSBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
386d692d6dfSBob King         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
387d692d6dfSBob King             .Times(0);
388d692d6dfSBob King 
389b4d18a45SShawn McCarney         // Create Device
3902874e902SShawn McCarney         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
391b4d18a45SShawn McCarney 
392b4d18a45SShawn McCarney         // Close Device
393d692d6dfSBob King         device.close(services);
394b4d18a45SShawn McCarney     }
395b4d18a45SShawn McCarney 
396b4d18a45SShawn McCarney     // Test where fails: closing I2C interface fails
397b4d18a45SShawn McCarney     {
398b4d18a45SShawn McCarney         // Create mock I2CInterface
3992874e902SShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
400b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
401b4d18a45SShawn McCarney         EXPECT_CALL(*i2cInterface, close)
402b4d18a45SShawn McCarney             .Times(1)
403b4d18a45SShawn McCarney             .WillOnce(Throw(
404b4d18a45SShawn McCarney                 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
405b4d18a45SShawn McCarney 
40681a2f90bSShawn McCarney         // Create mock services.  Expect logError() and logI2CError() to be
40781a2f90bSShawn McCarney         // called.
408d692d6dfSBob King         MockServices services{};
40981a2f90bSShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
410d692d6dfSBob King         MockJournal& journal = services.getMockJournal();
411d692d6dfSBob King         std::vector<std::string> expectedErrMessagesException{
412d692d6dfSBob King             "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
413d692d6dfSBob King         EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
414d692d6dfSBob King             .Times(1);
415d692d6dfSBob King         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
41681a2f90bSShawn McCarney         EXPECT_CALL(errorLogging,
41781a2f90bSShawn McCarney                     logI2CError(Entry::Level::Notice, Ref(journal),
41881a2f90bSShawn McCarney                                 "/dev/i2c-1", 0x70, 0))
41981a2f90bSShawn McCarney             .Times(1);
420d692d6dfSBob King 
421b4d18a45SShawn McCarney         // Create Device
4222874e902SShawn McCarney         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
423b4d18a45SShawn McCarney 
424b4d18a45SShawn McCarney         // Close Device
425d692d6dfSBob King         device.close(services);
426b4d18a45SShawn McCarney     }
427b4d18a45SShawn McCarney }
428b4d18a45SShawn McCarney 
TEST_F(DeviceTests,Configure)4292874e902SShawn McCarney TEST_F(DeviceTests, Configure)
430eb7bec4aSShawn McCarney {
43148033bf6SShawn McCarney     // Test where device is not present
43248033bf6SShawn McCarney     {
43348033bf6SShawn McCarney         // Create mock services.  No logging should occur.
43448033bf6SShawn McCarney         MockServices services{};
43548033bf6SShawn McCarney         MockJournal& journal = services.getMockJournal();
43648033bf6SShawn McCarney         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
43748033bf6SShawn McCarney         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
43848033bf6SShawn McCarney 
43948033bf6SShawn McCarney         // Create PresenceDetection.  Indicates device is not present.
4402874e902SShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
4412874e902SShawn McCarney         {
4422874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
4432874e902SShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
4442874e902SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
4452874e902SShawn McCarney             actions.emplace_back(std::move(action));
4462874e902SShawn McCarney             presenceDetection =
4472874e902SShawn McCarney                 std::make_unique<PresenceDetection>(std::move(actions));
4482874e902SShawn McCarney         }
44948033bf6SShawn McCarney 
45048033bf6SShawn McCarney         // Create Configuration.  Action inside it should not be executed.
4512874e902SShawn McCarney         std::unique_ptr<Configuration> configuration{};
4522874e902SShawn McCarney         {
45348033bf6SShawn McCarney             std::optional<double> volts{};
4542874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
4552874e902SShawn McCarney             EXPECT_CALL(*action, execute).Times(0);
4562874e902SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
4572874e902SShawn McCarney             actions.emplace_back(std::move(action));
458*f5402197SPatrick Williams             configuration =
459*f5402197SPatrick Williams                 std::make_unique<Configuration>(volts, std::move(actions));
4602874e902SShawn McCarney         }
46148033bf6SShawn McCarney 
46248033bf6SShawn McCarney         // Create Device
46348033bf6SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
4642874e902SShawn McCarney         Device device{"reg2",
4652874e902SShawn McCarney                       true,
4662874e902SShawn McCarney                       deviceInvPath,
4672874e902SShawn McCarney                       std::move(i2cInterface),
4682874e902SShawn McCarney                       std::move(presenceDetection),
4692874e902SShawn McCarney                       std::move(configuration)};
47048033bf6SShawn McCarney 
47148033bf6SShawn McCarney         // Call configure().  Should do nothing.
4722874e902SShawn McCarney         device.configure(services, *system, *chassis);
47348033bf6SShawn McCarney     }
47448033bf6SShawn McCarney 
475eb7bec4aSShawn McCarney     // Test where Configuration and Rails were not specified in constructor
476eb7bec4aSShawn McCarney     {
4775cfe5103SBob King         // Create mock services.  No logging should occur.
47823243f84SBob King         MockServices services{};
4795cfe5103SBob King         MockJournal& journal = services.getMockJournal();
4805cfe5103SBob King         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
4815cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
48223243f84SBob King 
483eb7bec4aSShawn McCarney         // Create Device
484eb7bec4aSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
4852874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
486eb7bec4aSShawn McCarney 
4875cfe5103SBob King         // Call configure().
4882874e902SShawn McCarney         device.configure(services, *system, *chassis);
489eb7bec4aSShawn McCarney     }
490eb7bec4aSShawn McCarney 
491eb7bec4aSShawn McCarney     // Test where Configuration and Rails were specified in constructor
492eb7bec4aSShawn McCarney     {
493eb7bec4aSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
494eb7bec4aSShawn McCarney 
4955cfe5103SBob King         // Create mock services.  Expect logDebug() to be called.
4965cfe5103SBob King         // For the Device and both Rails, should execute the Configuration
4975cfe5103SBob King         // and log a debug message.
4985cfe5103SBob King         MockServices services{};
4995cfe5103SBob King         MockJournal& journal = services.getMockJournal();
5002874e902SShawn McCarney         EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
5015cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
5025cfe5103SBob King             .Times(1);
5035cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
5045cfe5103SBob King             .Times(1);
5055cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
5065cfe5103SBob King 
507eb7bec4aSShawn McCarney         // Create Rail vdd0
508eb7bec4aSShawn McCarney         {
509eb7bec4aSShawn McCarney             // Create Configuration for Rail
510eb7bec4aSShawn McCarney             std::optional<double> volts{1.3};
5112874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
512eb7bec4aSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
513eb7bec4aSShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
514eb7bec4aSShawn McCarney             actions.emplace_back(std::move(action));
5152874e902SShawn McCarney             auto configuration =
516eb7bec4aSShawn McCarney                 std::make_unique<Configuration>(volts, std::move(actions));
517eb7bec4aSShawn McCarney 
518eb7bec4aSShawn McCarney             // Create Rail
519*f5402197SPatrick Williams             auto rail =
520*f5402197SPatrick Williams                 std::make_unique<Rail>("vdd0", std::move(configuration));
521eb7bec4aSShawn McCarney             rails.emplace_back(std::move(rail));
522eb7bec4aSShawn McCarney         }
523eb7bec4aSShawn McCarney 
524eb7bec4aSShawn McCarney         // Create Rail vio0
525eb7bec4aSShawn McCarney         {
526eb7bec4aSShawn McCarney             // Create Configuration for Rail
527eb7bec4aSShawn McCarney             std::optional<double> volts{3.2};
5282874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
529eb7bec4aSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
530eb7bec4aSShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
531eb7bec4aSShawn McCarney             actions.emplace_back(std::move(action));
5322874e902SShawn McCarney             auto configuration =
533eb7bec4aSShawn McCarney                 std::make_unique<Configuration>(volts, std::move(actions));
534eb7bec4aSShawn McCarney 
535eb7bec4aSShawn McCarney             // Create Rail
536*f5402197SPatrick Williams             auto rail =
537*f5402197SPatrick Williams                 std::make_unique<Rail>("vio0", std::move(configuration));
538eb7bec4aSShawn McCarney             rails.emplace_back(std::move(rail));
539eb7bec4aSShawn McCarney         }
540eb7bec4aSShawn McCarney 
541eb7bec4aSShawn McCarney         // Create Configuration for Device
542eb7bec4aSShawn McCarney         std::optional<double> volts{};
5432874e902SShawn McCarney         auto action = std::make_unique<MockAction>();
544eb7bec4aSShawn McCarney         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
545eb7bec4aSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
546eb7bec4aSShawn McCarney         actions.emplace_back(std::move(action));
5472874e902SShawn McCarney         auto configuration =
548eb7bec4aSShawn McCarney             std::make_unique<Configuration>(volts, std::move(actions));
549eb7bec4aSShawn McCarney 
550eb7bec4aSShawn McCarney         // Create Device
551eb7bec4aSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
552eb7bec4aSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
55332252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
5542874e902SShawn McCarney         Device device{"reg2",
5552874e902SShawn McCarney                       true,
5562874e902SShawn McCarney                       deviceInvPath,
5572874e902SShawn McCarney                       std::move(i2cInterface),
5582874e902SShawn McCarney                       std::move(presenceDetection),
5592874e902SShawn McCarney                       std::move(configuration),
5602874e902SShawn McCarney                       std::move(phaseFaultDetection),
5612874e902SShawn McCarney                       std::move(rails)};
562eb7bec4aSShawn McCarney 
5635cfe5103SBob King         // Call configure().
5642874e902SShawn McCarney         device.configure(services, *system, *chassis);
565eb7bec4aSShawn McCarney     }
566eb7bec4aSShawn McCarney }
567eb7bec4aSShawn McCarney 
TEST_F(DeviceTests,DetectPhaseFaults)5681fd0b145SShawn McCarney TEST_F(DeviceTests, DetectPhaseFaults)
5691fd0b145SShawn McCarney {
5701fd0b145SShawn McCarney     // Test where device is not present
5711fd0b145SShawn McCarney     {
5721fd0b145SShawn McCarney         // Create mock services.  No errors should be logged.
5731fd0b145SShawn McCarney         MockServices services{};
5741fd0b145SShawn McCarney         MockJournal& journal = services.getMockJournal();
5751fd0b145SShawn McCarney         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
5761fd0b145SShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
5771fd0b145SShawn McCarney         EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
5781fd0b145SShawn McCarney 
5791fd0b145SShawn McCarney         // Create PresenceDetection.  Indicates device is not present.
5801fd0b145SShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
5811fd0b145SShawn McCarney         {
5821fd0b145SShawn McCarney             auto action = std::make_unique<MockAction>();
5831fd0b145SShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
5841fd0b145SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
5851fd0b145SShawn McCarney             actions.emplace_back(std::move(action));
5861fd0b145SShawn McCarney             presenceDetection =
5871fd0b145SShawn McCarney                 std::make_unique<PresenceDetection>(std::move(actions));
5881fd0b145SShawn McCarney         }
5891fd0b145SShawn McCarney 
5901fd0b145SShawn McCarney         // Create PhaseFaultDetection.  Action inside it should not be executed.
5911fd0b145SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
5921fd0b145SShawn McCarney         {
5931fd0b145SShawn McCarney             auto action = std::make_unique<MockAction>();
5941fd0b145SShawn McCarney             EXPECT_CALL(*action, execute).Times(0);
5951fd0b145SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
5961fd0b145SShawn McCarney             actions.emplace_back(std::move(action));
5971fd0b145SShawn McCarney             phaseFaultDetection =
5981fd0b145SShawn McCarney                 std::make_unique<PhaseFaultDetection>(std::move(actions));
5991fd0b145SShawn McCarney         }
6001fd0b145SShawn McCarney 
6011fd0b145SShawn McCarney         // Create Device
6021fd0b145SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
6031fd0b145SShawn McCarney         std::unique_ptr<Configuration> configuration{};
6041fd0b145SShawn McCarney         Device device{"reg2",
6051fd0b145SShawn McCarney                       true,
6061fd0b145SShawn McCarney                       deviceInvPath,
6071fd0b145SShawn McCarney                       std::move(i2cInterface),
6081fd0b145SShawn McCarney                       std::move(presenceDetection),
6091fd0b145SShawn McCarney                       std::move(configuration),
6101fd0b145SShawn McCarney                       std::move(phaseFaultDetection)};
6111fd0b145SShawn McCarney 
6121fd0b145SShawn McCarney         // Call detectPhaseFaults() 5 times.  Should do nothing.
6131fd0b145SShawn McCarney         for (int i = 1; i <= 5; ++i)
6141fd0b145SShawn McCarney         {
6151fd0b145SShawn McCarney             device.detectPhaseFaults(services, *system, *chassis);
6161fd0b145SShawn McCarney         }
6171fd0b145SShawn McCarney     }
6181fd0b145SShawn McCarney 
6191fd0b145SShawn McCarney     // Test where PhaseFaultDetection was not specified in constructor
6201fd0b145SShawn McCarney     {
6211fd0b145SShawn McCarney         // Create mock services.  No errors should be logged.
6221fd0b145SShawn McCarney         MockServices services{};
6231fd0b145SShawn McCarney         MockJournal& journal = services.getMockJournal();
6241fd0b145SShawn McCarney         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
6251fd0b145SShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
6261fd0b145SShawn McCarney         EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
6271fd0b145SShawn McCarney 
6281fd0b145SShawn McCarney         // Create Device
6291fd0b145SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
6301fd0b145SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
6311fd0b145SShawn McCarney 
6321fd0b145SShawn McCarney         // Call detectPhaseFaults() 5 times.  Should do nothing.
6331fd0b145SShawn McCarney         for (int i = 1; i <= 5; ++i)
6341fd0b145SShawn McCarney         {
6351fd0b145SShawn McCarney             device.detectPhaseFaults(services, *system, *chassis);
6361fd0b145SShawn McCarney         }
6371fd0b145SShawn McCarney     }
6381fd0b145SShawn McCarney 
6391fd0b145SShawn McCarney     // Test where PhaseFaultDetection was specified in constructor
6401fd0b145SShawn McCarney     {
6411fd0b145SShawn McCarney         // Create mock services with the following expectations:
6421fd0b145SShawn McCarney         // - 2 error messages in journal for N phase fault detected
6431fd0b145SShawn McCarney         // - 1 N phase fault error logged
6441fd0b145SShawn McCarney         MockServices services{};
6451fd0b145SShawn McCarney         MockJournal& journal = services.getMockJournal();
6461fd0b145SShawn McCarney         EXPECT_CALL(
6471fd0b145SShawn McCarney             journal,
6481fd0b145SShawn McCarney             logError("n phase fault detected in regulator reg2: count=1"))
6491fd0b145SShawn McCarney             .Times(1);
6501fd0b145SShawn McCarney         EXPECT_CALL(
6511fd0b145SShawn McCarney             journal,
6521fd0b145SShawn McCarney             logError("n phase fault detected in regulator reg2: count=2"))
6531fd0b145SShawn McCarney             .Times(1);
6541fd0b145SShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
6551fd0b145SShawn McCarney         EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
6561fd0b145SShawn McCarney 
6571fd0b145SShawn McCarney         // Create PhaseFaultDetection
6581fd0b145SShawn McCarney         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
6591fd0b145SShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
6601fd0b145SShawn McCarney         actions.push_back(std::move(action));
6611fd0b145SShawn McCarney         auto phaseFaultDetection =
6621fd0b145SShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
6631fd0b145SShawn McCarney 
6641fd0b145SShawn McCarney         // Create Device
6651fd0b145SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
6661fd0b145SShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
6671fd0b145SShawn McCarney         std::unique_ptr<Configuration> configuration{};
6681fd0b145SShawn McCarney         Device device{"reg2",
6691fd0b145SShawn McCarney                       true,
6701fd0b145SShawn McCarney                       deviceInvPath,
6711fd0b145SShawn McCarney                       std::move(i2cInterface),
6721fd0b145SShawn McCarney                       std::move(presenceDetection),
6731fd0b145SShawn McCarney                       std::move(configuration),
6741fd0b145SShawn McCarney                       std::move(phaseFaultDetection)};
6751fd0b145SShawn McCarney 
6761fd0b145SShawn McCarney         // Call detectPhaseFaults() 5 times
6771fd0b145SShawn McCarney         for (int i = 1; i <= 5; ++i)
6781fd0b145SShawn McCarney         {
6791fd0b145SShawn McCarney             device.detectPhaseFaults(services, *system, *chassis);
6801fd0b145SShawn McCarney         }
6811fd0b145SShawn McCarney     }
6821fd0b145SShawn McCarney }
6831fd0b145SShawn McCarney 
TEST_F(DeviceTests,GetConfiguration)6842874e902SShawn McCarney TEST_F(DeviceTests, GetConfiguration)
685afb7fc3fSShawn McCarney {
6860b1a0e7aSShawn McCarney     // Test where Configuration was not specified in constructor
6870b1a0e7aSShawn McCarney     {
68841a6b9f3SPatrick Williams         Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
6890b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration(), nullptr);
6900b1a0e7aSShawn McCarney     }
6910b1a0e7aSShawn McCarney 
6920b1a0e7aSShawn McCarney     // Test where Configuration was specified in constructor
6930b1a0e7aSShawn McCarney     {
6940b1a0e7aSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
6950b1a0e7aSShawn McCarney 
6960b1a0e7aSShawn McCarney         // Create Configuration
6970b1a0e7aSShawn McCarney         std::optional<double> volts{3.2};
6980b1a0e7aSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
6990b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
7000b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
7012874e902SShawn McCarney         auto configuration =
7020b1a0e7aSShawn McCarney             std::make_unique<Configuration>(volts, std::move(actions));
7030b1a0e7aSShawn McCarney 
7040b1a0e7aSShawn McCarney         // Create Device
7052874e902SShawn McCarney         Device device{"vdd_reg",
7060b1a0e7aSShawn McCarney                       true,
7072874e902SShawn McCarney                       deviceInvPath,
70841a6b9f3SPatrick Williams                       createI2CInterface(),
7090b1a0e7aSShawn McCarney                       std::move(presenceDetection),
7100b1a0e7aSShawn McCarney                       std::move(configuration)};
7110b1a0e7aSShawn McCarney         EXPECT_NE(device.getConfiguration(), nullptr);
7120b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
7130b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
7140b1a0e7aSShawn McCarney         EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
7150b1a0e7aSShawn McCarney     }
716afb7fc3fSShawn McCarney }
717afb7fc3fSShawn McCarney 
TEST_F(DeviceTests,GetFRU)7182874e902SShawn McCarney TEST_F(DeviceTests, GetFRU)
719afb7fc3fSShawn McCarney {
72041a6b9f3SPatrick Williams     Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
7212874e902SShawn McCarney     EXPECT_EQ(device.getFRU(), deviceInvPath);
722afb7fc3fSShawn McCarney }
723afb7fc3fSShawn McCarney 
TEST_F(DeviceTests,GetI2CInterface)7242874e902SShawn McCarney TEST_F(DeviceTests, GetI2CInterface)
725afb7fc3fSShawn McCarney {
726afb7fc3fSShawn McCarney     std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
727afb7fc3fSShawn McCarney     i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
7282874e902SShawn McCarney     Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
729afb7fc3fSShawn McCarney     EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
730a2461b34SShawn McCarney }
7310b1a0e7aSShawn McCarney 
TEST_F(DeviceTests,GetID)7322874e902SShawn McCarney TEST_F(DeviceTests, GetID)
7330b1a0e7aSShawn McCarney {
73441a6b9f3SPatrick Williams     Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
7350b1a0e7aSShawn McCarney     EXPECT_EQ(device.getID(), "vdd_reg");
7360b1a0e7aSShawn McCarney }
7370b1a0e7aSShawn McCarney 
TEST_F(DeviceTests,GetPhaseFaultDetection)7382874e902SShawn McCarney TEST_F(DeviceTests, GetPhaseFaultDetection)
73932252599SShawn McCarney {
74032252599SShawn McCarney     // Test where PhaseFaultDetection was not specified in constructor
74132252599SShawn McCarney     {
74241a6b9f3SPatrick Williams         Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
74332252599SShawn McCarney         EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
74432252599SShawn McCarney     }
74532252599SShawn McCarney 
74632252599SShawn McCarney     // Test where PhaseFaultDetection was specified in constructor
74732252599SShawn McCarney     {
74832252599SShawn McCarney         // Create PhaseFaultDetection
74932252599SShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
75032252599SShawn McCarney         actions.push_back(std::make_unique<MockAction>());
7512874e902SShawn McCarney         auto phaseFaultDetection =
75232252599SShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
75332252599SShawn McCarney 
75432252599SShawn McCarney         // Create Device
75532252599SShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
75632252599SShawn McCarney         std::unique_ptr<Configuration> configuration{};
7572874e902SShawn McCarney         Device device{"vdd_reg",
75832252599SShawn McCarney                       false,
7592874e902SShawn McCarney                       deviceInvPath,
76041a6b9f3SPatrick Williams                       createI2CInterface(),
76132252599SShawn McCarney                       std::move(presenceDetection),
76232252599SShawn McCarney                       std::move(configuration),
76332252599SShawn McCarney                       std::move(phaseFaultDetection)};
76432252599SShawn McCarney         EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
76532252599SShawn McCarney         EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
76632252599SShawn McCarney     }
76732252599SShawn McCarney }
76832252599SShawn McCarney 
TEST_F(DeviceTests,GetPresenceDetection)7692874e902SShawn McCarney TEST_F(DeviceTests, GetPresenceDetection)
7700b1a0e7aSShawn McCarney {
7710b1a0e7aSShawn McCarney     // Test where PresenceDetection was not specified in constructor
7720b1a0e7aSShawn McCarney     {
77341a6b9f3SPatrick Williams         Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
7740b1a0e7aSShawn McCarney         EXPECT_EQ(device.getPresenceDetection(), nullptr);
7750b1a0e7aSShawn McCarney     }
7760b1a0e7aSShawn McCarney 
7770b1a0e7aSShawn McCarney     // Test where PresenceDetection was specified in constructor
7780b1a0e7aSShawn McCarney     {
7790b1a0e7aSShawn McCarney         // Create PresenceDetection
7800b1a0e7aSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
7810b1a0e7aSShawn McCarney         actions.push_back(std::make_unique<MockAction>());
7822874e902SShawn McCarney         auto presenceDetection =
7830b1a0e7aSShawn McCarney             std::make_unique<PresenceDetection>(std::move(actions));
7840b1a0e7aSShawn McCarney 
7850b1a0e7aSShawn McCarney         // Create Device
78641a6b9f3SPatrick Williams         Device device{"vdd_reg", false, deviceInvPath, createI2CInterface(),
7872874e902SShawn McCarney                       std::move(presenceDetection)};
7880b1a0e7aSShawn McCarney         EXPECT_NE(device.getPresenceDetection(), nullptr);
7890b1a0e7aSShawn McCarney         EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
7900b1a0e7aSShawn McCarney     }
7910b1a0e7aSShawn McCarney }
7920b1a0e7aSShawn McCarney 
TEST_F(DeviceTests,GetRails)7932874e902SShawn McCarney TEST_F(DeviceTests, GetRails)
7940b1a0e7aSShawn McCarney {
7950b1a0e7aSShawn McCarney     // Test where no rails were specified in constructor
7960b1a0e7aSShawn McCarney     {
79741a6b9f3SPatrick Williams         Device device{"vdd_reg", true, deviceInvPath, createI2CInterface()};
7980b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails().size(), 0);
7990b1a0e7aSShawn McCarney     }
8000b1a0e7aSShawn McCarney 
8010b1a0e7aSShawn McCarney     // Test where rails were specified in constructor
8020b1a0e7aSShawn McCarney     {
8030b1a0e7aSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
8040b1a0e7aSShawn McCarney         std::unique_ptr<Configuration> configuration{};
80532252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
8060b1a0e7aSShawn McCarney 
8070b1a0e7aSShawn McCarney         // Create vector of Rail objects
8080b1a0e7aSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
8090b1a0e7aSShawn McCarney         rails.push_back(std::make_unique<Rail>("vdd0"));
8100b1a0e7aSShawn McCarney         rails.push_back(std::make_unique<Rail>("vdd1"));
8110b1a0e7aSShawn McCarney 
8120b1a0e7aSShawn McCarney         // Create Device
8132874e902SShawn McCarney         Device device{"vdd_reg",
8140b1a0e7aSShawn McCarney                       false,
8152874e902SShawn McCarney                       deviceInvPath,
81641a6b9f3SPatrick Williams                       createI2CInterface(),
8170b1a0e7aSShawn McCarney                       std::move(presenceDetection),
8180b1a0e7aSShawn McCarney                       std::move(configuration),
81932252599SShawn McCarney                       std::move(phaseFaultDetection),
8200b1a0e7aSShawn McCarney                       std::move(rails)};
8210b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails().size(), 2);
8220b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
8230b1a0e7aSShawn McCarney         EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
8240b1a0e7aSShawn McCarney     }
8250b1a0e7aSShawn McCarney }
8260b1a0e7aSShawn McCarney 
TEST_F(DeviceTests,IsPresent)8272874e902SShawn McCarney TEST_F(DeviceTests, IsPresent)
82848033bf6SShawn McCarney {
82948033bf6SShawn McCarney     // Test where PresenceDetection not specified in constructor
83048033bf6SShawn McCarney     {
83148033bf6SShawn McCarney         // Create Device
83248033bf6SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
8332874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
83448033bf6SShawn McCarney 
83548033bf6SShawn McCarney         // Create MockServices
83648033bf6SShawn McCarney         MockServices services{};
83748033bf6SShawn McCarney 
83848033bf6SShawn McCarney         // Since no PresenceDetection defined, isPresent() should return true
8392874e902SShawn McCarney         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
84048033bf6SShawn McCarney     }
84148033bf6SShawn McCarney 
84248033bf6SShawn McCarney     // Test where PresenceDetection was specified in constructor: Is present
84348033bf6SShawn McCarney     {
84448033bf6SShawn McCarney         // Create PresenceDetection.  Indicates device is present.
8452874e902SShawn McCarney         auto action = std::make_unique<MockAction>();
84648033bf6SShawn McCarney         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
84748033bf6SShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
84848033bf6SShawn McCarney         actions.emplace_back(std::move(action));
8492874e902SShawn McCarney         auto presenceDetection =
85048033bf6SShawn McCarney             std::make_unique<PresenceDetection>(std::move(actions));
85148033bf6SShawn McCarney 
85248033bf6SShawn McCarney         // Create Device
85348033bf6SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
8542874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
8552874e902SShawn McCarney                       std::move(presenceDetection)};
85648033bf6SShawn McCarney 
85748033bf6SShawn McCarney         // Create MockServices
85848033bf6SShawn McCarney         MockServices services{};
85948033bf6SShawn McCarney 
86048033bf6SShawn McCarney         // PresenceDetection::execute() and isPresent() should return true
8612874e902SShawn McCarney         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
86248033bf6SShawn McCarney     }
86348033bf6SShawn McCarney 
86448033bf6SShawn McCarney     // Test where PresenceDetection was specified in constructor: Is not present
86548033bf6SShawn McCarney     {
86648033bf6SShawn McCarney         // Create PresenceDetection.  Indicates device is not present.
8672874e902SShawn McCarney         auto action = std::make_unique<MockAction>();
86848033bf6SShawn McCarney         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
86948033bf6SShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
87048033bf6SShawn McCarney         actions.emplace_back(std::move(action));
8712874e902SShawn McCarney         auto presenceDetection =
87248033bf6SShawn McCarney             std::make_unique<PresenceDetection>(std::move(actions));
87348033bf6SShawn McCarney 
87448033bf6SShawn McCarney         // Create Device
87548033bf6SShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
8762874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
8772874e902SShawn McCarney                       std::move(presenceDetection)};
87848033bf6SShawn McCarney 
87948033bf6SShawn McCarney         // Create MockServices
88048033bf6SShawn McCarney         MockServices services{};
88148033bf6SShawn McCarney 
88248033bf6SShawn McCarney         // PresenceDetection::execute() and isPresent() should return false
8832874e902SShawn McCarney         EXPECT_FALSE(device.isPresent(services, *system, *chassis));
88448033bf6SShawn McCarney     }
88548033bf6SShawn McCarney }
88648033bf6SShawn McCarney 
TEST_F(DeviceTests,IsRegulator)8872874e902SShawn McCarney TEST_F(DeviceTests, IsRegulator)
8880b1a0e7aSShawn McCarney {
88941a6b9f3SPatrick Williams     Device device{"vdd_reg", false, deviceInvPath, createI2CInterface()};
8900b1a0e7aSShawn McCarney     EXPECT_EQ(device.isRegulator(), false);
8910b1a0e7aSShawn McCarney }
8928e1cd0b6SBob King 
TEST_F(DeviceTests,MonitorSensors)8932874e902SShawn McCarney TEST_F(DeviceTests, MonitorSensors)
8948e1cd0b6SBob King {
89548033bf6SShawn McCarney     // Test where device is not present
8968e1cd0b6SBob King     {
89717bac89eSShawn McCarney         // Create mock services.  No Sensors methods should be called.
8988a55292dSBob King         MockServices services{};
89917bac89eSShawn McCarney         MockSensors& sensors = services.getMockSensors();
90017bac89eSShawn McCarney         EXPECT_CALL(sensors, startRail).Times(0);
90117bac89eSShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
90217bac89eSShawn McCarney         EXPECT_CALL(sensors, endRail).Times(0);
9038a55292dSBob King 
90417bac89eSShawn McCarney         // Create SensorMonitoring.  Action inside it should not be executed.
9052874e902SShawn McCarney         std::unique_ptr<SensorMonitoring> sensorMonitoring{};
9062874e902SShawn McCarney         {
9072874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
9082874e902SShawn McCarney             EXPECT_CALL(*action, execute).Times(0);
9092874e902SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
9102874e902SShawn McCarney             actions.emplace_back(std::move(action));
9112874e902SShawn McCarney             sensorMonitoring =
9122874e902SShawn McCarney                 std::make_unique<SensorMonitoring>(std::move(actions));
9132874e902SShawn McCarney         }
9148e1cd0b6SBob King 
9158e1cd0b6SBob King         // Create Rail
9168e1cd0b6SBob King         std::unique_ptr<Configuration> configuration{};
9172874e902SShawn McCarney         auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
9182874e902SShawn McCarney                                            std::move(sensorMonitoring));
91917bac89eSShawn McCarney 
92017bac89eSShawn McCarney         // Create PresenceDetection.  Indicates device is not present.
9212874e902SShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
9222874e902SShawn McCarney         {
9232874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
9242874e902SShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
9252874e902SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
9262874e902SShawn McCarney             actions.emplace_back(std::move(action));
9272874e902SShawn McCarney             presenceDetection =
9282874e902SShawn McCarney                 std::make_unique<PresenceDetection>(std::move(actions));
9292874e902SShawn McCarney         }
9308e1cd0b6SBob King 
9318e1cd0b6SBob King         // Create Device
93217bac89eSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
9338e1cd0b6SBob King         std::unique_ptr<Configuration> deviceConfiguration{};
93432252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
93517bac89eSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
93617bac89eSShawn McCarney         rails.emplace_back(std::move(rail));
9372874e902SShawn McCarney         Device device{"reg2",
9382874e902SShawn McCarney                       true,
9392874e902SShawn McCarney                       deviceInvPath,
9402874e902SShawn McCarney                       std::move(i2cInterface),
9412874e902SShawn McCarney                       std::move(presenceDetection),
9422874e902SShawn McCarney                       std::move(deviceConfiguration),
9432874e902SShawn McCarney                       std::move(phaseFaultDetection),
9442874e902SShawn McCarney                       std::move(rails)};
9458e1cd0b6SBob King 
94617bac89eSShawn McCarney         // Call monitorSensors().  Should do nothing.
9472874e902SShawn McCarney         device.monitorSensors(services, *system, *chassis);
94817bac89eSShawn McCarney     }
94917bac89eSShawn McCarney 
95017bac89eSShawn McCarney     // Test where Rails were not specified in constructor
95117bac89eSShawn McCarney     {
95217bac89eSShawn McCarney         // Create mock services.  No Sensors methods should be called.
95317bac89eSShawn McCarney         MockServices services{};
95417bac89eSShawn McCarney         MockSensors& sensors = services.getMockSensors();
95517bac89eSShawn McCarney         EXPECT_CALL(sensors, startRail).Times(0);
95617bac89eSShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
95717bac89eSShawn McCarney         EXPECT_CALL(sensors, endRail).Times(0);
95817bac89eSShawn McCarney 
95917bac89eSShawn McCarney         // Create Device
96017bac89eSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
9612874e902SShawn McCarney         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
96217bac89eSShawn McCarney 
96317bac89eSShawn McCarney         // Call monitorSensors().  Should do nothing.
9642874e902SShawn McCarney         device.monitorSensors(services, *system, *chassis);
96517bac89eSShawn McCarney     }
96617bac89eSShawn McCarney 
96717bac89eSShawn McCarney     // Test where Rails were specified in constructor
96817bac89eSShawn McCarney     {
96917bac89eSShawn McCarney         // Create mock services.  Set Sensors service expectations.
97017bac89eSShawn McCarney         MockServices services{};
97117bac89eSShawn McCarney         MockSensors& sensors = services.getMockSensors();
9722874e902SShawn McCarney         EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
97317bac89eSShawn McCarney             .Times(1);
9742874e902SShawn McCarney         EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
97517bac89eSShawn McCarney             .Times(1);
97617bac89eSShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
97717bac89eSShawn McCarney         EXPECT_CALL(sensors, endRail(false)).Times(2);
97817bac89eSShawn McCarney 
97917bac89eSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
98017bac89eSShawn McCarney 
98117bac89eSShawn McCarney         // Create Rail vdd0
98217bac89eSShawn McCarney         {
98317bac89eSShawn McCarney             // Create SensorMonitoring for Rail
9842874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
98517bac89eSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
98617bac89eSShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
98717bac89eSShawn McCarney             actions.emplace_back(std::move(action));
9882874e902SShawn McCarney             auto sensorMonitoring =
98917bac89eSShawn McCarney                 std::make_unique<SensorMonitoring>(std::move(actions));
99017bac89eSShawn McCarney 
99117bac89eSShawn McCarney             // Create Rail
99217bac89eSShawn McCarney             std::unique_ptr<Configuration> configuration{};
9932874e902SShawn McCarney             auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
9942874e902SShawn McCarney                                                std::move(sensorMonitoring));
99517bac89eSShawn McCarney             rails.emplace_back(std::move(rail));
99617bac89eSShawn McCarney         }
99717bac89eSShawn McCarney 
99817bac89eSShawn McCarney         // Create Rail vio0
99917bac89eSShawn McCarney         {
100017bac89eSShawn McCarney             // Create SensorMonitoring for Rail
10012874e902SShawn McCarney             auto action = std::make_unique<MockAction>();
100217bac89eSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
100317bac89eSShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
100417bac89eSShawn McCarney             actions.emplace_back(std::move(action));
10052874e902SShawn McCarney             auto sensorMonitoring =
100617bac89eSShawn McCarney                 std::make_unique<SensorMonitoring>(std::move(actions));
100717bac89eSShawn McCarney 
100817bac89eSShawn McCarney             // Create Rail
100917bac89eSShawn McCarney             std::unique_ptr<Configuration> configuration{};
10102874e902SShawn McCarney             auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
10112874e902SShawn McCarney                                                std::move(sensorMonitoring));
101217bac89eSShawn McCarney             rails.emplace_back(std::move(rail));
101317bac89eSShawn McCarney         }
101417bac89eSShawn McCarney 
101517bac89eSShawn McCarney         // Create Device that contains Rails
101617bac89eSShawn McCarney         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
101717bac89eSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
101817bac89eSShawn McCarney         std::unique_ptr<Configuration> configuration{};
101932252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
10202874e902SShawn McCarney         Device device{"reg2",
10212874e902SShawn McCarney                       true,
10222874e902SShawn McCarney                       deviceInvPath,
10232874e902SShawn McCarney                       std::move(i2cInterface),
10242874e902SShawn McCarney                       std::move(presenceDetection),
10252874e902SShawn McCarney                       std::move(configuration),
10262874e902SShawn McCarney                       std::move(phaseFaultDetection),
10272874e902SShawn McCarney                       std::move(rails)};
102817bac89eSShawn McCarney 
102917bac89eSShawn McCarney         // Call monitorSensors().  Should monitor sensors in both rails.
10302874e902SShawn McCarney         device.monitorSensors(services, *system, *chassis);
10318e1cd0b6SBob King     }
10328e1cd0b6SBob King }
1033