xref: /openbmc/phosphor-power/phosphor-regulators/test/device_tests.cpp (revision 2874e9022035712b7c882e486b7efcaebb70dd6e)
1 /**
2  * Copyright © 2019 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
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 "mock_action.hpp"
23 #include "mock_error_logging.hpp"
24 #include "mock_journal.hpp"
25 #include "mock_sensors.hpp"
26 #include "mock_services.hpp"
27 #include "mocked_i2c_interface.hpp"
28 #include "phase_fault_detection.hpp"
29 #include "presence_detection.hpp"
30 #include "rail.hpp"
31 #include "rule.hpp"
32 #include "sensor_monitoring.hpp"
33 #include "sensors.hpp"
34 #include "system.hpp"
35 #include "test_sdbus_error.hpp"
36 #include "test_utils.hpp"
37 
38 #include <memory>
39 #include <optional>
40 #include <string>
41 #include <utility>
42 #include <vector>
43 
44 #include <gmock/gmock.h>
45 #include <gtest/gtest.h>
46 
47 using namespace phosphor::power::regulators;
48 using namespace phosphor::power::regulators::test_utils;
49 
50 using ::testing::A;
51 using ::testing::Ref;
52 using ::testing::Return;
53 using ::testing::Throw;
54 using ::testing::TypedEq;
55 
56 class DeviceTests : public ::testing::Test
57 {
58   public:
59     /**
60      * Constructor.
61      *
62      * Creates the Chassis and System objects needed for calling some Device
63      * methods.
64      */
65     DeviceTests() : ::testing::Test{}
66     {
67         // Create Chassis
68         auto chassis = std::make_unique<Chassis>(1, chassisInvPath);
69         this->chassis = chassis.get();
70 
71         // Create System
72         std::vector<std::unique_ptr<Rule>> rules{};
73         std::vector<std::unique_ptr<Chassis>> chassisVec{};
74         chassisVec.emplace_back(std::move(chassis));
75         this->system =
76             std::make_unique<System>(std::move(rules), std::move(chassisVec));
77     }
78 
79   protected:
80     const std::string deviceInvPath{
81         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"};
82     const std::string chassisInvPath{
83         "/xyz/openbmc_project/inventory/system/chassis"};
84 
85     // Note: This pointer does NOT need to be explicitly deleted.  The Chassis
86     // object is owned by the System object and will be automatically deleted.
87     Chassis* chassis{nullptr};
88 
89     std::unique_ptr<System> system{};
90 };
91 
92 TEST_F(DeviceTests, Constructor)
93 {
94     // Test where only required parameters are specified
95     {
96         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
97         i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
98         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
99         EXPECT_EQ(device.getID(), "vdd_reg");
100         EXPECT_EQ(device.isRegulator(), true);
101         EXPECT_EQ(device.getFRU(), deviceInvPath);
102         EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
103         EXPECT_EQ(device.getPresenceDetection(), nullptr);
104         EXPECT_EQ(device.getConfiguration(), nullptr);
105         EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
106         EXPECT_EQ(device.getRails().size(), 0);
107     }
108 
109     // Test where all parameters are specified
110     {
111         // Create I2CInterface
112         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
113         i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
114 
115         // Create PresenceDetection
116         std::vector<std::unique_ptr<Action>> actions{};
117         actions.push_back(std::make_unique<MockAction>());
118         auto presenceDetection =
119             std::make_unique<PresenceDetection>(std::move(actions));
120 
121         // Create Configuration
122         std::optional<double> volts{};
123         actions.clear();
124         actions.push_back(std::make_unique<MockAction>());
125         actions.push_back(std::make_unique<MockAction>());
126         auto configuration =
127             std::make_unique<Configuration>(volts, std::move(actions));
128 
129         // Create PhaseFaultDetection
130         actions.clear();
131         actions.push_back(std::make_unique<MockAction>());
132         actions.push_back(std::make_unique<MockAction>());
133         actions.push_back(std::make_unique<MockAction>());
134         auto phaseFaultDetection =
135             std::make_unique<PhaseFaultDetection>(std::move(actions));
136 
137         // Create vector of Rail objects
138         std::vector<std::unique_ptr<Rail>> rails{};
139         rails.push_back(std::make_unique<Rail>("vdd0"));
140         rails.push_back(std::make_unique<Rail>("vdd1"));
141 
142         // Create Device
143         Device device{"vdd_reg",
144                       false,
145                       deviceInvPath,
146                       std::move(i2cInterface),
147                       std::move(presenceDetection),
148                       std::move(configuration),
149                       std::move(phaseFaultDetection),
150                       std::move(rails)};
151         EXPECT_EQ(device.getID(), "vdd_reg");
152         EXPECT_EQ(device.isRegulator(), false);
153         EXPECT_EQ(device.getFRU(), deviceInvPath);
154         EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
155         EXPECT_NE(device.getPresenceDetection(), nullptr);
156         EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
157         EXPECT_NE(device.getConfiguration(), nullptr);
158         EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
159         EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
160         EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
161         EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 3);
162         EXPECT_EQ(device.getRails().size(), 2);
163     }
164 }
165 
166 TEST_F(DeviceTests, AddToIDMap)
167 {
168     std::unique_ptr<PresenceDetection> presenceDetection{};
169     std::unique_ptr<Configuration> configuration{};
170     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
171 
172     // Create vector of Rail objects
173     std::vector<std::unique_ptr<Rail>> rails{};
174     rails.push_back(std::make_unique<Rail>("vdd0"));
175     rails.push_back(std::make_unique<Rail>("vdd1"));
176 
177     // Create Device
178     Device device{"vdd_reg",
179                   false,
180                   deviceInvPath,
181                   std::move(createI2CInterface()),
182                   std::move(presenceDetection),
183                   std::move(configuration),
184                   std::move(phaseFaultDetection),
185                   std::move(rails)};
186 
187     // Add Device and Rail objects to an IDMap
188     IDMap idMap{};
189     device.addToIDMap(idMap);
190 
191     // Verify Device is in the IDMap
192     EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
193     EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
194 
195     // Verify all Rails are in the IDMap
196     EXPECT_NO_THROW(idMap.getRail("vdd0"));
197     EXPECT_NO_THROW(idMap.getRail("vdd1"));
198     EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
199 }
200 
201 TEST_F(DeviceTests, ClearCache)
202 {
203     // Test where Device does not contain a PresenceDetection object
204     try
205     {
206         Device device{"vdd_reg", false, deviceInvPath,
207                       std::move(createI2CInterface())};
208         device.clearCache();
209     }
210     catch (...)
211     {
212         ADD_FAILURE() << "Should not have caught exception.";
213     }
214 
215     // Test where Device contains a PresenceDetection object
216     {
217         // Create PresenceDetection
218         std::vector<std::unique_ptr<Action>> actions{};
219         auto presenceDetection =
220             std::make_unique<PresenceDetection>(std::move(actions));
221         PresenceDetection* presenceDetectionPtr = presenceDetection.get();
222 
223         // Create Device
224         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
225         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
226                       std::move(presenceDetection)};
227 
228         // Cache presence value in PresenceDetection
229         MockServices services{};
230         presenceDetectionPtr->execute(services, *system, *chassis, device);
231         EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
232 
233         // Clear cached data in Device
234         device.clearCache();
235 
236         // Verify presence value no longer cached in PresenceDetection
237         EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
238     }
239 }
240 
241 TEST_F(DeviceTests, ClearErrorHistory)
242 {
243     // Create SensorMonitoring.  Will fail with a DBus exception.
244     auto action = std::make_unique<MockAction>();
245     EXPECT_CALL(*action, execute)
246         .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
247     std::vector<std::unique_ptr<Action>> actions{};
248     actions.emplace_back(std::move(action));
249     auto sensorMonitoring =
250         std::make_unique<SensorMonitoring>(std::move(actions));
251 
252     // Create Rail
253     std::unique_ptr<Configuration> configuration{};
254     auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
255                                        std::move(sensorMonitoring));
256 
257     // Create Device that contains Rail
258     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
259     std::unique_ptr<PresenceDetection> presenceDetection{};
260     std::unique_ptr<Configuration> deviceConfiguration{};
261     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
262     std::vector<std::unique_ptr<Rail>> rails{};
263     rails.emplace_back(std::move(rail));
264     Device device{"reg2",
265                   true,
266                   deviceInvPath,
267                   std::move(i2cInterface),
268                   std::move(presenceDetection),
269                   std::move(deviceConfiguration),
270                   std::move(phaseFaultDetection),
271                   std::move(rails)};
272 
273     // Create mock services
274     MockServices services{};
275 
276     // Expect Sensors service to be called 5+5=10 times
277     MockSensors& sensors = services.getMockSensors();
278     EXPECT_CALL(sensors, startRail).Times(10);
279     EXPECT_CALL(sensors, setValue).Times(0);
280     EXPECT_CALL(sensors, endRail).Times(10);
281 
282     // Expect Journal service to be called 3+3=6 times to log error messages
283     MockJournal& journal = services.getMockJournal();
284     EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
285         .Times(6);
286     EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
287 
288     // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
289     MockErrorLogging& errorLogging = services.getMockErrorLogging();
290     EXPECT_CALL(errorLogging, logDBusError).Times(2);
291 
292     // Monitor sensors 5 times.  Should fail every time, write to journal 3
293     // times, and log one error.
294     for (int i = 1; i <= 5; ++i)
295     {
296         device.monitorSensors(services, *system, *chassis);
297     }
298 
299     // Clear error history
300     device.clearErrorHistory();
301 
302     // Monitor sensors 5 times again.  Should fail every time, write to journal
303     // 3 times, and log one error.
304     for (int i = 1; i <= 5; ++i)
305     {
306         device.monitorSensors(services, *system, *chassis);
307     }
308 }
309 
310 TEST_F(DeviceTests, Close)
311 {
312     // Test where works: I2C interface is not open
313     {
314         // Create mock I2CInterface
315         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
316         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
317         EXPECT_CALL(*i2cInterface, close).Times(0);
318 
319         // Create mock services.  No logError should occur.
320         MockServices services{};
321         MockJournal& journal = services.getMockJournal();
322         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
323         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
324             .Times(0);
325 
326         // Create Device
327         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
328 
329         // Close Device
330         device.close(services);
331     }
332 
333     // Test where works: I2C interface is open
334     {
335         // Create mock I2CInterface
336         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
337         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
338         EXPECT_CALL(*i2cInterface, close).Times(1);
339 
340         // Create mock services.  No logError should occur.
341         MockServices services{};
342         MockJournal& journal = services.getMockJournal();
343         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
344         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
345             .Times(0);
346 
347         // Create Device
348         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
349 
350         // Close Device
351         device.close(services);
352     }
353 
354     // Test where fails: closing I2C interface fails
355     {
356         // Create mock I2CInterface
357         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
358         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
359         EXPECT_CALL(*i2cInterface, close)
360             .Times(1)
361             .WillOnce(Throw(
362                 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
363 
364         // Create mock services.  Expect logError() and logI2CError() to be
365         // called.
366         MockServices services{};
367         MockErrorLogging& errorLogging = services.getMockErrorLogging();
368         MockJournal& journal = services.getMockJournal();
369         std::vector<std::string> expectedErrMessagesException{
370             "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
371         EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
372             .Times(1);
373         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
374         EXPECT_CALL(errorLogging,
375                     logI2CError(Entry::Level::Notice, Ref(journal),
376                                 "/dev/i2c-1", 0x70, 0))
377             .Times(1);
378 
379         // Create Device
380         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
381 
382         // Close Device
383         device.close(services);
384     }
385 }
386 
387 TEST_F(DeviceTests, Configure)
388 {
389     // Test where device is not present
390     {
391         // Create mock services.  No logging should occur.
392         MockServices services{};
393         MockJournal& journal = services.getMockJournal();
394         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
395         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
396 
397         // Create PresenceDetection.  Indicates device is not present.
398         std::unique_ptr<PresenceDetection> presenceDetection{};
399         {
400             auto action = std::make_unique<MockAction>();
401             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
402             std::vector<std::unique_ptr<Action>> actions{};
403             actions.emplace_back(std::move(action));
404             presenceDetection =
405                 std::make_unique<PresenceDetection>(std::move(actions));
406         }
407 
408         // Create Configuration.  Action inside it should not be executed.
409         std::unique_ptr<Configuration> configuration{};
410         {
411             std::optional<double> volts{};
412             auto action = std::make_unique<MockAction>();
413             EXPECT_CALL(*action, execute).Times(0);
414             std::vector<std::unique_ptr<Action>> actions{};
415             actions.emplace_back(std::move(action));
416             configuration =
417                 std::make_unique<Configuration>(volts, std::move(actions));
418         }
419 
420         // Create Device
421         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
422         Device device{"reg2",
423                       true,
424                       deviceInvPath,
425                       std::move(i2cInterface),
426                       std::move(presenceDetection),
427                       std::move(configuration)};
428 
429         // Call configure().  Should do nothing.
430         device.configure(services, *system, *chassis);
431     }
432 
433     // Test where Configuration and Rails were not specified in constructor
434     {
435         // Create mock services.  No logging should occur.
436         MockServices services{};
437         MockJournal& journal = services.getMockJournal();
438         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
439         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
440 
441         // Create Device
442         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
443         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
444 
445         // Call configure().
446         device.configure(services, *system, *chassis);
447     }
448 
449     // Test where Configuration and Rails were specified in constructor
450     {
451         std::vector<std::unique_ptr<Rail>> rails{};
452 
453         // Create mock services.  Expect logDebug() to be called.
454         // For the Device and both Rails, should execute the Configuration
455         // and log a debug message.
456         MockServices services{};
457         MockJournal& journal = services.getMockJournal();
458         EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
459         EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
460             .Times(1);
461         EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
462             .Times(1);
463         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
464 
465         // Create Rail vdd0
466         {
467             // Create Configuration for Rail
468             std::optional<double> volts{1.3};
469             auto action = std::make_unique<MockAction>();
470             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
471             std::vector<std::unique_ptr<Action>> actions{};
472             actions.emplace_back(std::move(action));
473             auto configuration =
474                 std::make_unique<Configuration>(volts, std::move(actions));
475 
476             // Create Rail
477             auto rail =
478                 std::make_unique<Rail>("vdd0", std::move(configuration));
479             rails.emplace_back(std::move(rail));
480         }
481 
482         // Create Rail vio0
483         {
484             // Create Configuration for Rail
485             std::optional<double> volts{3.2};
486             auto action = std::make_unique<MockAction>();
487             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
488             std::vector<std::unique_ptr<Action>> actions{};
489             actions.emplace_back(std::move(action));
490             auto configuration =
491                 std::make_unique<Configuration>(volts, std::move(actions));
492 
493             // Create Rail
494             auto rail =
495                 std::make_unique<Rail>("vio0", std::move(configuration));
496             rails.emplace_back(std::move(rail));
497         }
498 
499         // Create Configuration for Device
500         std::optional<double> volts{};
501         auto action = std::make_unique<MockAction>();
502         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
503         std::vector<std::unique_ptr<Action>> actions{};
504         actions.emplace_back(std::move(action));
505         auto configuration =
506             std::make_unique<Configuration>(volts, std::move(actions));
507 
508         // Create Device
509         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
510         std::unique_ptr<PresenceDetection> presenceDetection{};
511         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
512         Device device{"reg2",
513                       true,
514                       deviceInvPath,
515                       std::move(i2cInterface),
516                       std::move(presenceDetection),
517                       std::move(configuration),
518                       std::move(phaseFaultDetection),
519                       std::move(rails)};
520 
521         // Call configure().
522         device.configure(services, *system, *chassis);
523     }
524 }
525 
526 TEST_F(DeviceTests, GetConfiguration)
527 {
528     // Test where Configuration was not specified in constructor
529     {
530         Device device{"vdd_reg", true, deviceInvPath,
531                       std::move(createI2CInterface())};
532         EXPECT_EQ(device.getConfiguration(), nullptr);
533     }
534 
535     // Test where Configuration was specified in constructor
536     {
537         std::unique_ptr<PresenceDetection> presenceDetection{};
538 
539         // Create Configuration
540         std::optional<double> volts{3.2};
541         std::vector<std::unique_ptr<Action>> actions{};
542         actions.push_back(std::make_unique<MockAction>());
543         actions.push_back(std::make_unique<MockAction>());
544         auto configuration =
545             std::make_unique<Configuration>(volts, std::move(actions));
546 
547         // Create Device
548         Device device{"vdd_reg",
549                       true,
550                       deviceInvPath,
551                       std::move(createI2CInterface()),
552                       std::move(presenceDetection),
553                       std::move(configuration)};
554         EXPECT_NE(device.getConfiguration(), nullptr);
555         EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
556         EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
557         EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
558     }
559 }
560 
561 TEST_F(DeviceTests, GetFRU)
562 {
563     Device device{"vdd_reg", true, deviceInvPath,
564                   std::move(createI2CInterface())};
565     EXPECT_EQ(device.getFRU(), deviceInvPath);
566 }
567 
568 TEST_F(DeviceTests, GetI2CInterface)
569 {
570     std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
571     i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
572     Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
573     EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
574 }
575 
576 TEST_F(DeviceTests, GetID)
577 {
578     Device device{"vdd_reg", false, deviceInvPath,
579                   std::move(createI2CInterface())};
580     EXPECT_EQ(device.getID(), "vdd_reg");
581 }
582 
583 TEST_F(DeviceTests, GetPhaseFaultDetection)
584 {
585     // Test where PhaseFaultDetection was not specified in constructor
586     {
587         Device device{"vdd_reg", true, deviceInvPath,
588                       std::move(createI2CInterface())};
589         EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
590     }
591 
592     // Test where PhaseFaultDetection was specified in constructor
593     {
594         // Create PhaseFaultDetection
595         std::vector<std::unique_ptr<Action>> actions{};
596         actions.push_back(std::make_unique<MockAction>());
597         auto phaseFaultDetection =
598             std::make_unique<PhaseFaultDetection>(std::move(actions));
599 
600         // Create Device
601         std::unique_ptr<PresenceDetection> presenceDetection{};
602         std::unique_ptr<Configuration> configuration{};
603         Device device{"vdd_reg",
604                       false,
605                       deviceInvPath,
606                       std::move(createI2CInterface()),
607                       std::move(presenceDetection),
608                       std::move(configuration),
609                       std::move(phaseFaultDetection)};
610         EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
611         EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
612     }
613 }
614 
615 TEST_F(DeviceTests, GetPresenceDetection)
616 {
617     // Test where PresenceDetection was not specified in constructor
618     {
619         Device device{"vdd_reg", true, deviceInvPath,
620                       std::move(createI2CInterface())};
621         EXPECT_EQ(device.getPresenceDetection(), nullptr);
622     }
623 
624     // Test where PresenceDetection was specified in constructor
625     {
626         // Create PresenceDetection
627         std::vector<std::unique_ptr<Action>> actions{};
628         actions.push_back(std::make_unique<MockAction>());
629         auto presenceDetection =
630             std::make_unique<PresenceDetection>(std::move(actions));
631 
632         // Create Device
633         Device device{"vdd_reg", false, deviceInvPath,
634                       std::move(createI2CInterface()),
635                       std::move(presenceDetection)};
636         EXPECT_NE(device.getPresenceDetection(), nullptr);
637         EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
638     }
639 }
640 
641 TEST_F(DeviceTests, GetRails)
642 {
643     // Test where no rails were specified in constructor
644     {
645         Device device{"vdd_reg", true, deviceInvPath,
646                       std::move(createI2CInterface())};
647         EXPECT_EQ(device.getRails().size(), 0);
648     }
649 
650     // Test where rails were specified in constructor
651     {
652         std::unique_ptr<PresenceDetection> presenceDetection{};
653         std::unique_ptr<Configuration> configuration{};
654         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
655 
656         // Create vector of Rail objects
657         std::vector<std::unique_ptr<Rail>> rails{};
658         rails.push_back(std::make_unique<Rail>("vdd0"));
659         rails.push_back(std::make_unique<Rail>("vdd1"));
660 
661         // Create Device
662         Device device{"vdd_reg",
663                       false,
664                       deviceInvPath,
665                       std::move(createI2CInterface()),
666                       std::move(presenceDetection),
667                       std::move(configuration),
668                       std::move(phaseFaultDetection),
669                       std::move(rails)};
670         EXPECT_EQ(device.getRails().size(), 2);
671         EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
672         EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
673     }
674 }
675 
676 TEST_F(DeviceTests, IsPresent)
677 {
678     // Test where PresenceDetection not specified in constructor
679     {
680         // Create Device
681         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
682         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
683 
684         // Create MockServices
685         MockServices services{};
686 
687         // Since no PresenceDetection defined, isPresent() should return true
688         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
689     }
690 
691     // Test where PresenceDetection was specified in constructor: Is present
692     {
693         // Create PresenceDetection.  Indicates device is present.
694         auto action = std::make_unique<MockAction>();
695         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
696         std::vector<std::unique_ptr<Action>> actions{};
697         actions.emplace_back(std::move(action));
698         auto presenceDetection =
699             std::make_unique<PresenceDetection>(std::move(actions));
700 
701         // Create Device
702         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
703         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
704                       std::move(presenceDetection)};
705 
706         // Create MockServices
707         MockServices services{};
708 
709         // PresenceDetection::execute() and isPresent() should return true
710         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
711     }
712 
713     // Test where PresenceDetection was specified in constructor: Is not present
714     {
715         // Create PresenceDetection.  Indicates device is not present.
716         auto action = std::make_unique<MockAction>();
717         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
718         std::vector<std::unique_ptr<Action>> actions{};
719         actions.emplace_back(std::move(action));
720         auto presenceDetection =
721             std::make_unique<PresenceDetection>(std::move(actions));
722 
723         // Create Device
724         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
725         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
726                       std::move(presenceDetection)};
727 
728         // Create MockServices
729         MockServices services{};
730 
731         // PresenceDetection::execute() and isPresent() should return false
732         EXPECT_FALSE(device.isPresent(services, *system, *chassis));
733     }
734 }
735 
736 TEST_F(DeviceTests, IsRegulator)
737 {
738     Device device{"vdd_reg", false, deviceInvPath,
739                   std::move(createI2CInterface())};
740     EXPECT_EQ(device.isRegulator(), false);
741 }
742 
743 TEST_F(DeviceTests, MonitorSensors)
744 {
745     // Test where device is not present
746     {
747         // Create mock services.  No Sensors methods should be called.
748         MockServices services{};
749         MockSensors& sensors = services.getMockSensors();
750         EXPECT_CALL(sensors, startRail).Times(0);
751         EXPECT_CALL(sensors, setValue).Times(0);
752         EXPECT_CALL(sensors, endRail).Times(0);
753 
754         // Create SensorMonitoring.  Action inside it should not be executed.
755         std::unique_ptr<SensorMonitoring> sensorMonitoring{};
756         {
757             auto action = std::make_unique<MockAction>();
758             EXPECT_CALL(*action, execute).Times(0);
759             std::vector<std::unique_ptr<Action>> actions{};
760             actions.emplace_back(std::move(action));
761             sensorMonitoring =
762                 std::make_unique<SensorMonitoring>(std::move(actions));
763         }
764 
765         // Create Rail
766         std::unique_ptr<Configuration> configuration{};
767         auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
768                                            std::move(sensorMonitoring));
769 
770         // Create PresenceDetection.  Indicates device is not present.
771         std::unique_ptr<PresenceDetection> presenceDetection{};
772         {
773             auto action = std::make_unique<MockAction>();
774             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
775             std::vector<std::unique_ptr<Action>> actions{};
776             actions.emplace_back(std::move(action));
777             presenceDetection =
778                 std::make_unique<PresenceDetection>(std::move(actions));
779         }
780 
781         // Create Device
782         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
783         std::unique_ptr<Configuration> deviceConfiguration{};
784         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
785         std::vector<std::unique_ptr<Rail>> rails{};
786         rails.emplace_back(std::move(rail));
787         Device device{"reg2",
788                       true,
789                       deviceInvPath,
790                       std::move(i2cInterface),
791                       std::move(presenceDetection),
792                       std::move(deviceConfiguration),
793                       std::move(phaseFaultDetection),
794                       std::move(rails)};
795 
796         // Call monitorSensors().  Should do nothing.
797         device.monitorSensors(services, *system, *chassis);
798     }
799 
800     // Test where Rails were not specified in constructor
801     {
802         // Create mock services.  No Sensors methods should be called.
803         MockServices services{};
804         MockSensors& sensors = services.getMockSensors();
805         EXPECT_CALL(sensors, startRail).Times(0);
806         EXPECT_CALL(sensors, setValue).Times(0);
807         EXPECT_CALL(sensors, endRail).Times(0);
808 
809         // Create Device
810         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
811         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
812 
813         // Call monitorSensors().  Should do nothing.
814         device.monitorSensors(services, *system, *chassis);
815     }
816 
817     // Test where Rails were specified in constructor
818     {
819         // Create mock services.  Set Sensors service expectations.
820         MockServices services{};
821         MockSensors& sensors = services.getMockSensors();
822         EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
823             .Times(1);
824         EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
825             .Times(1);
826         EXPECT_CALL(sensors, setValue).Times(0);
827         EXPECT_CALL(sensors, endRail(false)).Times(2);
828 
829         std::vector<std::unique_ptr<Rail>> rails{};
830 
831         // Create Rail vdd0
832         {
833             // Create SensorMonitoring for Rail
834             auto action = std::make_unique<MockAction>();
835             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
836             std::vector<std::unique_ptr<Action>> actions{};
837             actions.emplace_back(std::move(action));
838             auto sensorMonitoring =
839                 std::make_unique<SensorMonitoring>(std::move(actions));
840 
841             // Create Rail
842             std::unique_ptr<Configuration> configuration{};
843             auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
844                                                std::move(sensorMonitoring));
845             rails.emplace_back(std::move(rail));
846         }
847 
848         // Create Rail vio0
849         {
850             // Create SensorMonitoring for Rail
851             auto action = std::make_unique<MockAction>();
852             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
853             std::vector<std::unique_ptr<Action>> actions{};
854             actions.emplace_back(std::move(action));
855             auto sensorMonitoring =
856                 std::make_unique<SensorMonitoring>(std::move(actions));
857 
858             // Create Rail
859             std::unique_ptr<Configuration> configuration{};
860             auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
861                                                std::move(sensorMonitoring));
862             rails.emplace_back(std::move(rail));
863         }
864 
865         // Create Device that contains Rails
866         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
867         std::unique_ptr<PresenceDetection> presenceDetection{};
868         std::unique_ptr<Configuration> configuration{};
869         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
870         Device device{"reg2",
871                       true,
872                       deviceInvPath,
873                       std::move(i2cInterface),
874                       std::move(presenceDetection),
875                       std::move(configuration),
876                       std::move(phaseFaultDetection),
877                       std::move(rails)};
878 
879         // Call monitorSensors().  Should monitor sensors in both rails.
880         device.monitorSensors(services, *system, *chassis);
881     }
882 }
883