1 /**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "action.hpp"
17 #include "chassis.hpp"
18 #include "configuration.hpp"
19 #include "device.hpp"
20 #include "i2c_interface.hpp"
21 #include "id_map.hpp"
22 #include "log_phase_fault_action.hpp"
23 #include "mock_action.hpp"
24 #include "mock_error_logging.hpp"
25 #include "mock_journal.hpp"
26 #include "mock_sensors.hpp"
27 #include "mock_services.hpp"
28 #include "mocked_i2c_interface.hpp"
29 #include "phase_fault.hpp"
30 #include "phase_fault_detection.hpp"
31 #include "presence_detection.hpp"
32 #include "rail.hpp"
33 #include "rule.hpp"
34 #include "sensor_monitoring.hpp"
35 #include "sensors.hpp"
36 #include "system.hpp"
37 #include "test_sdbus_error.hpp"
38 #include "test_utils.hpp"
39
40 #include <memory>
41 #include <stdexcept>
42 #include <string>
43 #include <utility>
44 #include <vector>
45
46 #include <gmock/gmock.h>
47 #include <gtest/gtest.h>
48
49 using namespace phosphor::power::regulators;
50 using namespace phosphor::power::regulators::test_utils;
51
52 using ::testing::A;
53 using ::testing::Return;
54 using ::testing::Throw;
55 using ::testing::TypedEq;
56
57 class ChassisTests : public ::testing::Test
58 {
59 public:
60 /**
61 * Constructor.
62 *
63 * Creates the System object needed for calling some Chassis methods.
64 */
ChassisTests()65 ChassisTests() : ::testing::Test{}
66 {
67 std::vector<std::unique_ptr<Rule>> rules{};
68 std::vector<std::unique_ptr<Chassis>> chassis{};
69 system = std::make_unique<System>(std::move(rules), std::move(chassis));
70 }
71
72 protected:
73 const std::string defaultInventoryPath{
74 "/xyz/openbmc_project/inventory/system/chassis"};
75
76 std::unique_ptr<System> system{};
77 };
78
TEST_F(ChassisTests,Constructor)79 TEST_F(ChassisTests, Constructor)
80 {
81 // Test where works: Only required parameters are specified
82 {
83 Chassis chassis{2, defaultInventoryPath};
84 EXPECT_EQ(chassis.getNumber(), 2);
85 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
86 EXPECT_EQ(chassis.getDevices().size(), 0);
87 }
88
89 // Test where works: All parameters are specified
90 {
91 // Create vector of Device objects
92 std::vector<std::unique_ptr<Device>> devices{};
93 devices.emplace_back(createDevice("vdd_reg1"));
94 devices.emplace_back(createDevice("vdd_reg2"));
95
96 // Create Chassis
97 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
98 EXPECT_EQ(chassis.getNumber(), 1);
99 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
100 EXPECT_EQ(chassis.getDevices().size(), 2);
101 }
102
103 // Test where fails: Invalid chassis number < 1
104 try
105 {
106 Chassis chassis{0, defaultInventoryPath};
107 ADD_FAILURE() << "Should not have reached this line.";
108 }
109 catch (const std::invalid_argument& e)
110 {
111 EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
112 }
113 catch (...)
114 {
115 ADD_FAILURE() << "Should not have caught exception.";
116 }
117 }
118
TEST_F(ChassisTests,AddToIDMap)119 TEST_F(ChassisTests, AddToIDMap)
120 {
121 // Create vector of Device objects
122 std::vector<std::unique_ptr<Device>> devices{};
123 devices.emplace_back(createDevice("reg1", {"rail1"}));
124 devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
125 devices.emplace_back(createDevice("reg3"));
126
127 // Create Chassis
128 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
129
130 // Add Device and Rail objects within the Chassis to an IDMap
131 IDMap idMap{};
132 chassis.addToIDMap(idMap);
133
134 // Verify all Devices are in the IDMap
135 EXPECT_NO_THROW(idMap.getDevice("reg1"));
136 EXPECT_NO_THROW(idMap.getDevice("reg2"));
137 EXPECT_NO_THROW(idMap.getDevice("reg3"));
138 EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
139
140 // Verify all Rails are in the IDMap
141 EXPECT_NO_THROW(idMap.getRail("rail1"));
142 EXPECT_NO_THROW(idMap.getRail("rail2a"));
143 EXPECT_NO_THROW(idMap.getRail("rail2b"));
144 EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
145 }
146
TEST_F(ChassisTests,ClearCache)147 TEST_F(ChassisTests, ClearCache)
148 {
149 // Create PresenceDetection
150 std::vector<std::unique_ptr<Action>> actions{};
151 auto presenceDetection =
152 std::make_unique<PresenceDetection>(std::move(actions));
153 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
154
155 // Create Device that contains PresenceDetection
156 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
157 auto device = std::make_unique<Device>(
158 "reg1", true,
159 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
160 std::move(i2cInterface), std::move(presenceDetection));
161 Device* devicePtr = device.get();
162
163 // Create Chassis that contains Device
164 std::vector<std::unique_ptr<Device>> devices{};
165 devices.emplace_back(std::move(device));
166 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
167
168 // Cache presence value in PresenceDetection
169 MockServices services{};
170 presenceDetectionPtr->execute(services, *system, chassis, *devicePtr);
171 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
172
173 // Clear cached data in Chassis
174 chassis.clearCache();
175
176 // Verify presence value no longer cached in PresenceDetection
177 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
178 }
179
TEST_F(ChassisTests,ClearErrorHistory)180 TEST_F(ChassisTests, ClearErrorHistory)
181 {
182 // Create SensorMonitoring. Will fail with a DBus exception.
183 auto action = std::make_unique<MockAction>();
184 EXPECT_CALL(*action, execute)
185 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
186 std::vector<std::unique_ptr<Action>> actions{};
187 actions.emplace_back(std::move(action));
188 auto sensorMonitoring =
189 std::make_unique<SensorMonitoring>(std::move(actions));
190
191 // Create Rail
192 std::unique_ptr<Configuration> configuration{};
193 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
194 std::move(sensorMonitoring));
195
196 // Create Device that contains Rail
197 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
198 std::unique_ptr<PresenceDetection> presenceDetection{};
199 std::unique_ptr<Configuration> deviceConfiguration{};
200 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
201 std::vector<std::unique_ptr<Rail>> rails{};
202 rails.emplace_back(std::move(rail));
203 auto device = std::make_unique<Device>(
204 "reg1", true,
205 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
206 std::move(i2cInterface), std::move(presenceDetection),
207 std::move(deviceConfiguration), std::move(phaseFaultDetection),
208 std::move(rails));
209
210 // Create Chassis that contains Device
211 std::vector<std::unique_ptr<Device>> devices{};
212 devices.emplace_back(std::move(device));
213 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
214
215 // Create lambda that sets MockServices expectations. The lambda allows
216 // us to set expectations multiple times without duplicate code.
217 auto setExpectations = [](MockServices& services) {
218 // Expect Sensors service to be called 10 times
219 MockSensors& sensors = services.getMockSensors();
220 EXPECT_CALL(sensors, startRail).Times(10);
221 EXPECT_CALL(sensors, setValue).Times(0);
222 EXPECT_CALL(sensors, endRail).Times(10);
223
224 // Expect Journal service to be called 6 times to log error messages
225 MockJournal& journal = services.getMockJournal();
226 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
227 .Times(6);
228 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
229
230 // Expect ErrorLogging service to be called once to log a DBus error
231 MockErrorLogging& errorLogging = services.getMockErrorLogging();
232 EXPECT_CALL(errorLogging, logDBusError).Times(1);
233 };
234
235 // Monitor sensors 10 times. Verify errors logged.
236 {
237 // Create mock services. Set expectations via lambda.
238 MockServices services{};
239 setExpectations(services);
240
241 for (int i = 1; i <= 10; ++i)
242 {
243 chassis.monitorSensors(services, *system);
244 }
245 }
246
247 // Clear error history
248 chassis.clearErrorHistory();
249
250 // Monitor sensors 10 more times. Verify errors logged again.
251 {
252 // Create mock services. Set expectations via lambda.
253 MockServices services{};
254 setExpectations(services);
255
256 for (int i = 1; i <= 10; ++i)
257 {
258 chassis.monitorSensors(services, *system);
259 }
260 }
261 }
262
TEST_F(ChassisTests,CloseDevices)263 TEST_F(ChassisTests, CloseDevices)
264 {
265 // Test where no devices were specified in constructor
266 {
267 // Create mock services. Expect logDebug() to be called.
268 MockServices services{};
269 MockJournal& journal = services.getMockJournal();
270 EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
271
272 // Create Chassis
273 Chassis chassis{2, defaultInventoryPath};
274
275 // Call closeDevices()
276 chassis.closeDevices(services);
277 }
278
279 // Test where devices were specified in constructor
280 {
281 std::vector<std::unique_ptr<Device>> devices{};
282
283 // Create mock services. Expect logDebug() to be called.
284 MockServices services{};
285 MockJournal& journal = services.getMockJournal();
286 EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
287
288 // Create Device vdd0_reg
289 {
290 // Create mock I2CInterface: isOpen() and close() should be called
291 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
292 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
293 EXPECT_CALL(*i2cInterface, close).Times(1);
294
295 // Create Device
296 auto device = std::make_unique<Device>(
297 "vdd0_reg", true,
298 "/xyz/openbmc_project/inventory/"
299 "system/chassis/motherboard/vdd0_reg",
300 std::move(i2cInterface));
301 devices.emplace_back(std::move(device));
302 }
303
304 // Create Device vdd1_reg
305 {
306 // Create mock I2CInterface: isOpen() and close() should be called
307 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
308 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
309 EXPECT_CALL(*i2cInterface, close).Times(1);
310
311 // Create Device
312 auto device = std::make_unique<Device>(
313 "vdd1_reg", true,
314 "/xyz/openbmc_project/inventory/"
315 "system/chassis/motherboard/vdd1_reg",
316 std::move(i2cInterface));
317 devices.emplace_back(std::move(device));
318 }
319
320 // Create Chassis
321 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
322
323 // Call closeDevices()
324 chassis.closeDevices(services);
325 }
326 }
327
TEST_F(ChassisTests,Configure)328 TEST_F(ChassisTests, Configure)
329 {
330 // Test where no devices were specified in constructor
331 {
332 // Create mock services. Expect logInfo() to be called.
333 MockServices services{};
334 MockJournal& journal = services.getMockJournal();
335 EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
336 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
337 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
338
339 // Create Chassis
340 Chassis chassis{1, defaultInventoryPath};
341
342 // Call configure()
343 chassis.configure(services, *system);
344 }
345
346 // Test where devices were specified in constructor
347 {
348 std::vector<std::unique_ptr<Device>> devices{};
349
350 // Create mock services. Expect logInfo() and logDebug() to be called.
351 MockServices services{};
352 MockJournal& journal = services.getMockJournal();
353 EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
354 EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
355 .Times(1);
356 EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
357 .Times(1);
358 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
359
360 // Create Device vdd0_reg
361 {
362 // Create Configuration
363 std::vector<std::unique_ptr<Action>> actions{};
364 auto configuration =
365 std::make_unique<Configuration>(1.3, std::move(actions));
366
367 // Create Device
368 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
369 std::unique_ptr<PresenceDetection> presenceDetection{};
370 auto device = std::make_unique<Device>(
371 "vdd0_reg", true,
372 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
373 "vdd0_reg",
374 std::move(i2cInterface), std::move(presenceDetection),
375 std::move(configuration));
376 devices.emplace_back(std::move(device));
377 }
378
379 // Create Device vdd1_reg
380 {
381 // Create Configuration
382 std::vector<std::unique_ptr<Action>> actions{};
383 auto configuration =
384 std::make_unique<Configuration>(1.2, std::move(actions));
385
386 // Create Device
387 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
388 std::unique_ptr<PresenceDetection> presenceDetection{};
389 auto device = std::make_unique<Device>(
390 "vdd1_reg", true,
391 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
392 "vdd1_reg",
393 std::move(i2cInterface), std::move(presenceDetection),
394 std::move(configuration));
395 devices.emplace_back(std::move(device));
396 }
397
398 // Create Chassis
399 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
400
401 // Call configure()
402 chassis.configure(services, *system);
403 }
404 }
405
TEST_F(ChassisTests,DetectPhaseFaults)406 TEST_F(ChassisTests, DetectPhaseFaults)
407 {
408 // Test where no devices were specified in constructor
409 {
410 // Create mock services. No errors should be logged.
411 MockServices services{};
412 MockJournal& journal = services.getMockJournal();
413 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
414 MockErrorLogging& errorLogging = services.getMockErrorLogging();
415 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
416
417 // Create Chassis
418 Chassis chassis{1, defaultInventoryPath};
419
420 // Call detectPhaseFaults() 5 times. Should do nothing.
421 for (int i = 1; i <= 5; ++i)
422 {
423 chassis.detectPhaseFaults(services, *system);
424 }
425 }
426
427 // Test where devices were specified in constructor
428 {
429 // Create mock services with the following expectations:
430 // - 2 error messages in journal for N phase fault detected in reg0
431 // - 2 error messages in journal for N phase fault detected in reg1
432 // - 1 N phase fault error logged for reg0
433 // - 1 N phase fault error logged for reg1
434 MockServices services{};
435 MockJournal& journal = services.getMockJournal();
436 EXPECT_CALL(
437 journal,
438 logError("n phase fault detected in regulator reg0: count=1"))
439 .Times(1);
440 EXPECT_CALL(
441 journal,
442 logError("n phase fault detected in regulator reg0: count=2"))
443 .Times(1);
444 EXPECT_CALL(
445 journal,
446 logError("n phase fault detected in regulator reg1: count=1"))
447 .Times(1);
448 EXPECT_CALL(
449 journal,
450 logError("n phase fault detected in regulator reg1: count=2"))
451 .Times(1);
452 MockErrorLogging& errorLogging = services.getMockErrorLogging();
453 EXPECT_CALL(errorLogging, logPhaseFault).Times(2);
454
455 std::vector<std::unique_ptr<Device>> devices{};
456
457 // Create Device reg0
458 {
459 // Create PhaseFaultDetection
460 auto action =
461 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
462 std::vector<std::unique_ptr<Action>> actions{};
463 actions.push_back(std::move(action));
464 auto phaseFaultDetection =
465 std::make_unique<PhaseFaultDetection>(std::move(actions));
466
467 // Create Device
468 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
469 std::unique_ptr<PresenceDetection> presenceDetection{};
470 std::unique_ptr<Configuration> configuration{};
471 auto device = std::make_unique<Device>(
472 "reg0", true,
473 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
474 "reg0",
475 std::move(i2cInterface), std::move(presenceDetection),
476 std::move(configuration), std::move(phaseFaultDetection));
477 devices.emplace_back(std::move(device));
478 }
479
480 // Create Device reg1
481 {
482 // Create PhaseFaultDetection
483 auto action =
484 std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
485 std::vector<std::unique_ptr<Action>> actions{};
486 actions.push_back(std::move(action));
487 auto phaseFaultDetection =
488 std::make_unique<PhaseFaultDetection>(std::move(actions));
489
490 // Create Device
491 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
492 std::unique_ptr<PresenceDetection> presenceDetection{};
493 std::unique_ptr<Configuration> configuration{};
494 auto device = std::make_unique<Device>(
495 "reg1", true,
496 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
497 "reg1",
498 std::move(i2cInterface), std::move(presenceDetection),
499 std::move(configuration), std::move(phaseFaultDetection));
500 devices.emplace_back(std::move(device));
501 }
502
503 // Create Chassis
504 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
505
506 // Call detectPhaseFaults() 5 times
507 for (int i = 1; i <= 5; ++i)
508 {
509 chassis.detectPhaseFaults(services, *system);
510 }
511 }
512 }
513
TEST_F(ChassisTests,GetDevices)514 TEST_F(ChassisTests, GetDevices)
515 {
516 // Test where no devices were specified in constructor
517 {
518 Chassis chassis{2, defaultInventoryPath};
519 EXPECT_EQ(chassis.getDevices().size(), 0);
520 }
521
522 // Test where devices were specified in constructor
523 {
524 // Create vector of Device objects
525 std::vector<std::unique_ptr<Device>> devices{};
526 devices.emplace_back(createDevice("vdd_reg1"));
527 devices.emplace_back(createDevice("vdd_reg2"));
528
529 // Create Chassis
530 Chassis chassis{1, defaultInventoryPath, std::move(devices)};
531 EXPECT_EQ(chassis.getDevices().size(), 2);
532 EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
533 EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
534 }
535 }
536
TEST_F(ChassisTests,GetInventoryPath)537 TEST_F(ChassisTests, GetInventoryPath)
538 {
539 Chassis chassis{3, defaultInventoryPath};
540 EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
541 }
542
TEST_F(ChassisTests,GetNumber)543 TEST_F(ChassisTests, GetNumber)
544 {
545 Chassis chassis{3, defaultInventoryPath};
546 EXPECT_EQ(chassis.getNumber(), 3);
547 }
548
TEST_F(ChassisTests,MonitorSensors)549 TEST_F(ChassisTests, MonitorSensors)
550 {
551 // Test where no devices were specified in constructor
552 {
553 // Create mock services. No Sensors methods should be called.
554 MockServices services{};
555 MockSensors& sensors = services.getMockSensors();
556 EXPECT_CALL(sensors, startRail).Times(0);
557 EXPECT_CALL(sensors, setValue).Times(0);
558 EXPECT_CALL(sensors, endRail).Times(0);
559
560 // Create Chassis
561 Chassis chassis{1, defaultInventoryPath};
562
563 // Call monitorSensors(). Should do nothing.
564 chassis.monitorSensors(services, *system);
565 }
566
567 // Test where devices were specified in constructor
568 {
569 // Create mock services. Set Sensors service expectations.
570 MockServices services{};
571 MockSensors& sensors = services.getMockSensors();
572 EXPECT_CALL(sensors, startRail("vdd0",
573 "/xyz/openbmc_project/inventory/system/"
574 "chassis/motherboard/vdd0_reg",
575 defaultInventoryPath))
576 .Times(1);
577 EXPECT_CALL(sensors, startRail("vdd1",
578 "/xyz/openbmc_project/inventory/system/"
579 "chassis/motherboard/vdd1_reg",
580 defaultInventoryPath))
581 .Times(1);
582 EXPECT_CALL(sensors, setValue).Times(0);
583 EXPECT_CALL(sensors, endRail(false)).Times(2);
584
585 std::vector<std::unique_ptr<Device>> devices{};
586
587 // Create Device vdd0_reg
588 {
589 // Create SensorMonitoring for Rail
590 auto action = std::make_unique<MockAction>();
591 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
592 std::vector<std::unique_ptr<Action>> actions{};
593 actions.emplace_back(std::move(action));
594 auto sensorMonitoring =
595 std::make_unique<SensorMonitoring>(std::move(actions));
596
597 // Create Rail
598 std::unique_ptr<Configuration> configuration{};
599 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
600 std::move(sensorMonitoring));
601
602 // Create Device
603 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
604 std::unique_ptr<PresenceDetection> presenceDetection{};
605 std::unique_ptr<Configuration> deviceConfiguration{};
606 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
607 std::vector<std::unique_ptr<Rail>> rails{};
608 rails.emplace_back(std::move(rail));
609 auto device = std::make_unique<Device>(
610 "vdd0_reg", true,
611 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
612 "vdd0_reg",
613 std::move(i2cInterface), std::move(presenceDetection),
614 std::move(deviceConfiguration), std::move(phaseFaultDetection),
615 std::move(rails));
616 devices.emplace_back(std::move(device));
617 }
618
619 // Create Device vdd1_reg
620 {
621 // Create SensorMonitoring for Rail
622 auto action = std::make_unique<MockAction>();
623 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
624 std::vector<std::unique_ptr<Action>> actions{};
625 actions.emplace_back(std::move(action));
626 auto sensorMonitoring =
627 std::make_unique<SensorMonitoring>(std::move(actions));
628
629 // Create Rail
630 std::unique_ptr<Configuration> configuration{};
631 auto rail = std::make_unique<Rail>("vdd1", std::move(configuration),
632 std::move(sensorMonitoring));
633
634 // Create Device
635 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
636 std::unique_ptr<PresenceDetection> presenceDetection{};
637 std::unique_ptr<Configuration> deviceConfiguration{};
638 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
639 std::vector<std::unique_ptr<Rail>> rails{};
640 rails.emplace_back(std::move(rail));
641 auto device = std::make_unique<Device>(
642 "vdd1_reg", true,
643 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
644 "vdd1_reg",
645 std::move(i2cInterface), std::move(presenceDetection),
646 std::move(deviceConfiguration), std::move(phaseFaultDetection),
647 std::move(rails));
648 devices.emplace_back(std::move(device));
649 }
650
651 // Create Chassis that contains Devices
652 Chassis chassis{2, defaultInventoryPath, std::move(devices)};
653
654 // Call monitorSensors()
655 chassis.monitorSensors(services, *system);
656 }
657 }
658