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