18a3afd70SShawn McCarney /**
28a3afd70SShawn McCarney  * Copyright © 2020 IBM Corporation
38a3afd70SShawn McCarney  *
48a3afd70SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
58a3afd70SShawn McCarney  * you may not use this file except in compliance with the License.
68a3afd70SShawn McCarney  * You may obtain a copy of the License at
78a3afd70SShawn McCarney  *
88a3afd70SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
98a3afd70SShawn McCarney  *
108a3afd70SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
118a3afd70SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
128a3afd70SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a3afd70SShawn McCarney  * See the License for the specific language governing permissions and
148a3afd70SShawn McCarney  * limitations under the License.
158a3afd70SShawn McCarney  */
16525e20c9SShawn McCarney #include "action.hpp"
178a3afd70SShawn McCarney #include "chassis.hpp"
18525e20c9SShawn McCarney #include "configuration.hpp"
198a3afd70SShawn McCarney #include "device.hpp"
208a3afd70SShawn McCarney #include "i2c_interface.hpp"
21db0b833cSShawn McCarney #include "id_map.hpp"
22525e20c9SShawn McCarney #include "journal.hpp"
23525e20c9SShawn McCarney #include "mock_journal.hpp"
2423243f84SBob King #include "mock_services.hpp"
25050531f5SShawn McCarney #include "mocked_i2c_interface.hpp"
26a2c81a61SBob King #include "pmbus_read_sensor_action.hpp"
27525e20c9SShawn McCarney #include "presence_detection.hpp"
28525e20c9SShawn McCarney #include "rail.hpp"
29525e20c9SShawn McCarney #include "rule.hpp"
30525e20c9SShawn McCarney #include "system.hpp"
318a3afd70SShawn McCarney #include "test_utils.hpp"
328a3afd70SShawn McCarney 
338a3afd70SShawn McCarney #include <memory>
348a3afd70SShawn McCarney #include <stdexcept>
35525e20c9SShawn McCarney #include <string>
368a3afd70SShawn McCarney #include <utility>
378a3afd70SShawn McCarney #include <vector>
388a3afd70SShawn McCarney 
39a2c81a61SBob King #include <gmock/gmock.h>
408a3afd70SShawn McCarney #include <gtest/gtest.h>
418a3afd70SShawn McCarney 
428a3afd70SShawn McCarney using namespace phosphor::power::regulators;
438a3afd70SShawn McCarney using namespace phosphor::power::regulators::test_utils;
448a3afd70SShawn McCarney 
45a2c81a61SBob King using ::testing::A;
46050531f5SShawn McCarney using ::testing::Return;
47a2c81a61SBob King using ::testing::TypedEq;
48050531f5SShawn McCarney 
498a3afd70SShawn McCarney TEST(ChassisTests, Constructor)
508a3afd70SShawn McCarney {
518a3afd70SShawn McCarney     // Test where works: Only required parameters are specified
528a3afd70SShawn McCarney     {
538a3afd70SShawn McCarney         Chassis chassis{2};
548a3afd70SShawn McCarney         EXPECT_EQ(chassis.getNumber(), 2);
558a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 0);
568a3afd70SShawn McCarney     }
578a3afd70SShawn McCarney 
588a3afd70SShawn McCarney     // Test where works: All parameters are specified
598a3afd70SShawn McCarney     {
608a3afd70SShawn McCarney         // Create vector of Device objects
618a3afd70SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
62db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg1"));
63db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg2"));
648a3afd70SShawn McCarney 
658a3afd70SShawn McCarney         // Create Chassis
668a3afd70SShawn McCarney         Chassis chassis{1, std::move(devices)};
678a3afd70SShawn McCarney         EXPECT_EQ(chassis.getNumber(), 1);
688a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 2);
698a3afd70SShawn McCarney     }
708a3afd70SShawn McCarney 
718a3afd70SShawn McCarney     // Test where fails: Invalid chassis number < 1
728a3afd70SShawn McCarney     try
738a3afd70SShawn McCarney     {
748a3afd70SShawn McCarney         Chassis chassis{0};
758a3afd70SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
768a3afd70SShawn McCarney     }
778a3afd70SShawn McCarney     catch (const std::invalid_argument& e)
788a3afd70SShawn McCarney     {
798a3afd70SShawn McCarney         EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
808a3afd70SShawn McCarney     }
818a3afd70SShawn McCarney     catch (...)
828a3afd70SShawn McCarney     {
838a3afd70SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
848a3afd70SShawn McCarney     }
858a3afd70SShawn McCarney }
868a3afd70SShawn McCarney 
87db0b833cSShawn McCarney TEST(ChassisTests, AddToIDMap)
88db0b833cSShawn McCarney {
89db0b833cSShawn McCarney     // Create vector of Device objects
90db0b833cSShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
91db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg1", {"rail1"}));
92db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
93db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg3"));
94db0b833cSShawn McCarney 
95db0b833cSShawn McCarney     // Create Chassis
96db0b833cSShawn McCarney     Chassis chassis{1, std::move(devices)};
97db0b833cSShawn McCarney 
98db0b833cSShawn McCarney     // Add Device and Rail objects within the Chassis to an IDMap
99db0b833cSShawn McCarney     IDMap idMap{};
100db0b833cSShawn McCarney     chassis.addToIDMap(idMap);
101db0b833cSShawn McCarney 
102db0b833cSShawn McCarney     // Verify all Devices are in the IDMap
103db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg1"));
104db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg2"));
105db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg3"));
106db0b833cSShawn McCarney     EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
107db0b833cSShawn McCarney 
108db0b833cSShawn McCarney     // Verify all Rails are in the IDMap
109db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail1"));
110db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2a"));
111db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2b"));
112db0b833cSShawn McCarney     EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
113db0b833cSShawn McCarney }
114db0b833cSShawn McCarney 
115050531f5SShawn McCarney TEST(ChassisTests, CloseDevices)
116050531f5SShawn McCarney {
117050531f5SShawn McCarney     // Test where no devices were specified in constructor
118050531f5SShawn McCarney     {
119050531f5SShawn McCarney         // Create Chassis
120050531f5SShawn McCarney         Chassis chassis{2};
121050531f5SShawn McCarney 
122050531f5SShawn McCarney         // Call closeDevices()
123050531f5SShawn McCarney         journal::clear();
124050531f5SShawn McCarney         chassis.closeDevices();
125050531f5SShawn McCarney         EXPECT_EQ(journal::getErrMessages().size(), 0);
126050531f5SShawn McCarney         EXPECT_EQ(journal::getInfoMessages().size(), 0);
127050531f5SShawn McCarney         std::vector<std::string> expectedDebugMessages{
128050531f5SShawn McCarney             "Closing devices in chassis 2"};
129050531f5SShawn McCarney         EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
130050531f5SShawn McCarney     }
131050531f5SShawn McCarney 
132050531f5SShawn McCarney     // Test where devices were specified in constructor
133050531f5SShawn McCarney     {
134050531f5SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
135050531f5SShawn McCarney 
136050531f5SShawn McCarney         // Create Device vdd0_reg
137050531f5SShawn McCarney         {
138050531f5SShawn McCarney             // Create mock I2CInterface: isOpen() and close() should be called
139050531f5SShawn McCarney             std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
140050531f5SShawn McCarney                 std::make_unique<i2c::MockedI2CInterface>();
141050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
142050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, close).Times(1);
143050531f5SShawn McCarney 
144050531f5SShawn McCarney             // Create Device
145050531f5SShawn McCarney             std::unique_ptr<Device> device = std::make_unique<Device>(
146050531f5SShawn McCarney                 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
147050531f5SShawn McCarney                 std::move(i2cInterface));
148050531f5SShawn McCarney             devices.emplace_back(std::move(device));
149050531f5SShawn McCarney         }
150050531f5SShawn McCarney 
151050531f5SShawn McCarney         // Create Device vdd1_reg
152050531f5SShawn McCarney         {
153050531f5SShawn McCarney             // Create mock I2CInterface: isOpen() and close() should be called
154050531f5SShawn McCarney             std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
155050531f5SShawn McCarney                 std::make_unique<i2c::MockedI2CInterface>();
156050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
157050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, close).Times(1);
158050531f5SShawn McCarney 
159050531f5SShawn McCarney             // Create Device
160050531f5SShawn McCarney             std::unique_ptr<Device> device = std::make_unique<Device>(
161050531f5SShawn McCarney                 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
162050531f5SShawn McCarney                 std::move(i2cInterface));
163050531f5SShawn McCarney             devices.emplace_back(std::move(device));
164050531f5SShawn McCarney         }
165050531f5SShawn McCarney 
166050531f5SShawn McCarney         // Create Chassis
167050531f5SShawn McCarney         Chassis chassis{1, std::move(devices)};
168050531f5SShawn McCarney 
169050531f5SShawn McCarney         // Call closeDevices()
170050531f5SShawn McCarney         journal::clear();
171050531f5SShawn McCarney         chassis.closeDevices();
172050531f5SShawn McCarney         EXPECT_EQ(journal::getErrMessages().size(), 0);
173050531f5SShawn McCarney         EXPECT_EQ(journal::getInfoMessages().size(), 0);
174050531f5SShawn McCarney         std::vector<std::string> expectedDebugMessages{
175050531f5SShawn McCarney             "Closing devices in chassis 1"};
176050531f5SShawn McCarney         EXPECT_EQ(journal::getDebugMessages(), expectedDebugMessages);
177050531f5SShawn McCarney     }
178050531f5SShawn McCarney }
179050531f5SShawn McCarney 
180525e20c9SShawn McCarney TEST(ChassisTests, Configure)
181525e20c9SShawn McCarney {
182525e20c9SShawn McCarney     // Test where no devices were specified in constructor
183525e20c9SShawn McCarney     {
1845cfe5103SBob King         // Create mock services.  Expect logInfo() to be called.
18523243f84SBob King         MockServices services{};
1865cfe5103SBob King         MockJournal& journal = services.getMockJournal();
1875cfe5103SBob King         EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
1885cfe5103SBob King         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
1895cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
19023243f84SBob King 
191525e20c9SShawn McCarney         // Create Chassis
192525e20c9SShawn McCarney         std::unique_ptr<Chassis> chassis = std::make_unique<Chassis>(1);
193525e20c9SShawn McCarney         Chassis* chassisPtr = chassis.get();
194525e20c9SShawn McCarney 
195525e20c9SShawn McCarney         // Create System that contains Chassis
196525e20c9SShawn McCarney         std::vector<std::unique_ptr<Rule>> rules{};
197525e20c9SShawn McCarney         std::vector<std::unique_ptr<Chassis>> chassisVec{};
198525e20c9SShawn McCarney         chassisVec.emplace_back(std::move(chassis));
199525e20c9SShawn McCarney         System system{std::move(rules), std::move(chassisVec)};
200525e20c9SShawn McCarney 
201525e20c9SShawn McCarney         // Call configure()
20223243f84SBob King         chassisPtr->configure(services, system);
203525e20c9SShawn McCarney     }
204525e20c9SShawn McCarney 
205525e20c9SShawn McCarney     // Test where devices were specified in constructor
206525e20c9SShawn McCarney     {
207525e20c9SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
208525e20c9SShawn McCarney 
2095cfe5103SBob King         // Create mock services.  Expect logInfo() and logDebug() to be called.
2105cfe5103SBob King         MockServices services{};
2115cfe5103SBob King         MockJournal& journal = services.getMockJournal();
2125cfe5103SBob King         EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
2135cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
2145cfe5103SBob King             .Times(1);
2155cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
2165cfe5103SBob King             .Times(1);
2175cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
2185cfe5103SBob King 
219525e20c9SShawn McCarney         // Create Device vdd0_reg
220525e20c9SShawn McCarney         {
221525e20c9SShawn McCarney             // Create Configuration
222525e20c9SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
223525e20c9SShawn McCarney             std::unique_ptr<Configuration> configuration =
224525e20c9SShawn McCarney                 std::make_unique<Configuration>(1.3, std::move(actions));
225525e20c9SShawn McCarney 
226525e20c9SShawn McCarney             // Create Device
227525e20c9SShawn McCarney             std::unique_ptr<i2c::I2CInterface> i2cInterface =
228525e20c9SShawn McCarney                 createI2CInterface();
229525e20c9SShawn McCarney             std::unique_ptr<PresenceDetection> presenceDetection{};
230525e20c9SShawn McCarney             std::unique_ptr<Device> device = std::make_unique<Device>(
231525e20c9SShawn McCarney                 "vdd0_reg", true, "/system/chassis/motherboard/vdd0_reg",
232525e20c9SShawn McCarney                 std::move(i2cInterface), std::move(presenceDetection),
233525e20c9SShawn McCarney                 std::move(configuration));
234525e20c9SShawn McCarney             devices.emplace_back(std::move(device));
235525e20c9SShawn McCarney         }
236525e20c9SShawn McCarney 
237525e20c9SShawn McCarney         // Create Device vdd1_reg
238525e20c9SShawn McCarney         {
239525e20c9SShawn McCarney             // Create Configuration
240525e20c9SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
241525e20c9SShawn McCarney             std::unique_ptr<Configuration> configuration =
242525e20c9SShawn McCarney                 std::make_unique<Configuration>(1.2, std::move(actions));
243525e20c9SShawn McCarney 
244525e20c9SShawn McCarney             // Create Device
245525e20c9SShawn McCarney             std::unique_ptr<i2c::I2CInterface> i2cInterface =
246525e20c9SShawn McCarney                 createI2CInterface();
247525e20c9SShawn McCarney             std::unique_ptr<PresenceDetection> presenceDetection{};
248525e20c9SShawn McCarney             std::unique_ptr<Device> device = std::make_unique<Device>(
249525e20c9SShawn McCarney                 "vdd1_reg", true, "/system/chassis/motherboard/vdd1_reg",
250525e20c9SShawn McCarney                 std::move(i2cInterface), std::move(presenceDetection),
251525e20c9SShawn McCarney                 std::move(configuration));
252525e20c9SShawn McCarney             devices.emplace_back(std::move(device));
253525e20c9SShawn McCarney         }
254525e20c9SShawn McCarney 
255525e20c9SShawn McCarney         // Create Chassis
256525e20c9SShawn McCarney         std::unique_ptr<Chassis> chassis =
257525e20c9SShawn McCarney             std::make_unique<Chassis>(2, std::move(devices));
258525e20c9SShawn McCarney         Chassis* chassisPtr = chassis.get();
259525e20c9SShawn McCarney 
260525e20c9SShawn McCarney         // Create System that contains Chassis
261525e20c9SShawn McCarney         std::vector<std::unique_ptr<Rule>> rules{};
262525e20c9SShawn McCarney         std::vector<std::unique_ptr<Chassis>> chassisVec{};
263525e20c9SShawn McCarney         chassisVec.emplace_back(std::move(chassis));
264525e20c9SShawn McCarney         System system{std::move(rules), std::move(chassisVec)};
265525e20c9SShawn McCarney 
266525e20c9SShawn McCarney         // Call configure()
26723243f84SBob King         chassisPtr->configure(services, system);
268525e20c9SShawn McCarney     }
269525e20c9SShawn McCarney }
270525e20c9SShawn McCarney 
2718a3afd70SShawn McCarney TEST(ChassisTests, GetDevices)
2728a3afd70SShawn McCarney {
2738a3afd70SShawn McCarney     // Test where no devices were specified in constructor
2748a3afd70SShawn McCarney     {
2758a3afd70SShawn McCarney         Chassis chassis{2};
2768a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 0);
2778a3afd70SShawn McCarney     }
2788a3afd70SShawn McCarney 
2798a3afd70SShawn McCarney     // Test where devices were specified in constructor
2808a3afd70SShawn McCarney     {
2818a3afd70SShawn McCarney         // Create vector of Device objects
2828a3afd70SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
283db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg1"));
284db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg2"));
2858a3afd70SShawn McCarney 
2868a3afd70SShawn McCarney         // Create Chassis
2878a3afd70SShawn McCarney         Chassis chassis{1, std::move(devices)};
2888a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 2);
2898a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
2908a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
2918a3afd70SShawn McCarney     }
2928a3afd70SShawn McCarney }
2938a3afd70SShawn McCarney 
2948a3afd70SShawn McCarney TEST(ChassisTests, GetNumber)
2958a3afd70SShawn McCarney {
2968a3afd70SShawn McCarney     Chassis chassis{3};
2978a3afd70SShawn McCarney     EXPECT_EQ(chassis.getNumber(), 3);
2988a3afd70SShawn McCarney }
299a2c81a61SBob King 
300a2c81a61SBob King TEST(ChassisTests, MonitorSensors)
301a2c81a61SBob King {
302a2c81a61SBob King     // Test where no devices were specified in constructor
303a2c81a61SBob King     {
304*8a55292dSBob King         // Create mock services.  No logging should occur.
305*8a55292dSBob King         MockServices services{};
306*8a55292dSBob King         MockJournal& journal = services.getMockJournal();
307*8a55292dSBob King         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
308*8a55292dSBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
309*8a55292dSBob King 
310a2c81a61SBob King         // Create Chassis
311a2c81a61SBob King         std::vector<std::unique_ptr<Device>> devices{};
312a2c81a61SBob King         std::unique_ptr<Chassis> chassis =
313a2c81a61SBob King             std::make_unique<Chassis>(1, std::move(devices));
314a2c81a61SBob King         Chassis* chassisPtr = chassis.get();
315a2c81a61SBob King 
316a2c81a61SBob King         // Create System that contains Chassis
317a2c81a61SBob King         std::vector<std::unique_ptr<Rule>> rules{};
318a2c81a61SBob King         std::vector<std::unique_ptr<Chassis>> chassisVec{};
319a2c81a61SBob King         chassisVec.emplace_back(std::move(chassis));
320a2c81a61SBob King         System system{std::move(rules), std::move(chassisVec)};
321a2c81a61SBob King 
322a2c81a61SBob King         // Call monitorSensors().  Should do nothing.
323*8a55292dSBob King         chassisPtr->monitorSensors(services, system);
324a2c81a61SBob King     }
325a2c81a61SBob King 
326a2c81a61SBob King     // Test where devices were specified in constructor
327a2c81a61SBob King     {
328*8a55292dSBob King         // Create mock services.  No logging should occur.
329*8a55292dSBob King         MockServices services{};
330*8a55292dSBob King         MockJournal& journal = services.getMockJournal();
331*8a55292dSBob King         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
332*8a55292dSBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
333*8a55292dSBob King 
334a2c81a61SBob King         std::vector<std::unique_ptr<Device>> devices{};
335a2c81a61SBob King 
336a2c81a61SBob King         // Create PMBusReadSensorAction
337a2c81a61SBob King         pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
338a2c81a61SBob King         uint8_t command = 0x8C;
339a2c81a61SBob King         pmbus_utils::SensorDataFormat format{
340a2c81a61SBob King             pmbus_utils::SensorDataFormat::linear_11};
341a2c81a61SBob King         std::optional<int8_t> exponent{};
342a2c81a61SBob King         std::unique_ptr<PMBusReadSensorAction> action =
343a2c81a61SBob King             std::make_unique<PMBusReadSensorAction>(type, command, format,
344a2c81a61SBob King                                                     exponent);
345a2c81a61SBob King 
346a2c81a61SBob King         // Create mock I2CInterface.  A two-byte read should occur.
347a2c81a61SBob King         std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
348a2c81a61SBob King             std::make_unique<i2c::MockedI2CInterface>();
349a2c81a61SBob King         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
350a2c81a61SBob King         EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
351a2c81a61SBob King             .Times(1);
352a2c81a61SBob King 
353a2c81a61SBob King         // Create SensorMonitoring
354a2c81a61SBob King         std::vector<std::unique_ptr<Action>> actions{};
355a2c81a61SBob King         actions.emplace_back(std::move(action));
356a2c81a61SBob King         std::unique_ptr<SensorMonitoring> sensorMonitoring =
357a2c81a61SBob King             std::make_unique<SensorMonitoring>(std::move(actions));
358a2c81a61SBob King 
359a2c81a61SBob King         // Create Rail
360a2c81a61SBob King         std::vector<std::unique_ptr<Rail>> rails{};
361a2c81a61SBob King         std::unique_ptr<Configuration> configuration{};
362a2c81a61SBob King         std::unique_ptr<Rail> rail = std::make_unique<Rail>(
363a2c81a61SBob King             "vdd0", std::move(configuration), std::move(sensorMonitoring));
364a2c81a61SBob King         rails.emplace_back(std::move(rail));
365a2c81a61SBob King 
366a2c81a61SBob King         // Create Device
367a2c81a61SBob King         std::unique_ptr<PresenceDetection> presenceDetection{};
368a2c81a61SBob King         std::unique_ptr<Configuration> deviceConfiguration{};
369a2c81a61SBob King         std::unique_ptr<Device> device = std::make_unique<Device>(
370a2c81a61SBob King             "reg1", true, "/system/chassis/motherboard/reg1",
371a2c81a61SBob King             std::move(i2cInterface), std::move(presenceDetection),
372a2c81a61SBob King             std::move(deviceConfiguration), std::move(rails));
373a2c81a61SBob King 
374a2c81a61SBob King         // Create Chassis
375a2c81a61SBob King         devices.emplace_back(std::move(device));
376a2c81a61SBob King         std::unique_ptr<Chassis> chassis =
377a2c81a61SBob King             std::make_unique<Chassis>(1, std::move(devices));
378a2c81a61SBob King         Chassis* chassisPtr = chassis.get();
379a2c81a61SBob King 
380a2c81a61SBob King         // Create System that contains Chassis
381a2c81a61SBob King         std::vector<std::unique_ptr<Rule>> rules{};
382a2c81a61SBob King         std::vector<std::unique_ptr<Chassis>> chassisVec{};
383a2c81a61SBob King         chassisVec.emplace_back(std::move(chassis));
384a2c81a61SBob King         System system{std::move(rules), std::move(chassisVec)};
385a2c81a61SBob King 
386a2c81a61SBob King         // Call monitorSensors()
387*8a55292dSBob King         chassisPtr->monitorSensors(services, system);
388a2c81a61SBob King     }
389a2c81a61SBob King }
390