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     std::unique_ptr<SensorMonitoring> sensorMonitoring{};
247     {
248         auto action = std::make_unique<MockAction>();
249         EXPECT_CALL(*action, execute)
250             .WillRepeatedly(Throw(TestSDBusError{"DBus Error"}));
251         std::vector<std::unique_ptr<Action>> actions{};
252         actions.emplace_back(std::move(action));
253         sensorMonitoring =
254             std::make_unique<SensorMonitoring>(std::move(actions));
255     }
256 
257     // Create Rail
258     std::unique_ptr<Configuration> configuration{};
259     auto rail = std::make_unique<Rail>("vdd", std::move(configuration),
260                                        std::move(sensorMonitoring));
261 
262     // Create PhaseFaultDetection.  Will log an N phase fault.
263     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
264     {
265         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
266         std::vector<std::unique_ptr<Action>> actions{};
267         actions.emplace_back(std::move(action));
268         phaseFaultDetection =
269             std::make_unique<PhaseFaultDetection>(std::move(actions));
270     }
271 
272     // Create Device
273     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
274     std::unique_ptr<PresenceDetection> presenceDetection{};
275     std::unique_ptr<Configuration> deviceConfiguration{};
276     std::vector<std::unique_ptr<Rail>> rails{};
277     rails.emplace_back(std::move(rail));
278     Device device{"reg2",
279                   true,
280                   deviceInvPath,
281                   std::move(i2cInterface),
282                   std::move(presenceDetection),
283                   std::move(deviceConfiguration),
284                   std::move(phaseFaultDetection),
285                   std::move(rails)};
286 
287     // Create lambda that sets MockServices expectations.  The lambda allows
288     // us to set expectations multiple times without duplicate code.
289     auto setExpectations = [](MockServices& services) {
290         // Set Journal service expectations:
291         // - 6 error messages for D-Bus errors
292         // - 6 error messages for inability to monitor sensors
293         // - 2 error messages for the N phase fault
294         MockJournal& journal = services.getMockJournal();
295         EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"}))
296             .Times(6);
297         EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd"))
298             .Times(6);
299         EXPECT_CALL(
300             journal,
301             logError("n phase fault detected in regulator reg2: count=1"))
302             .Times(1);
303         EXPECT_CALL(
304             journal,
305             logError("n phase fault detected in regulator reg2: count=2"))
306             .Times(1);
307 
308         // Set ErrorLogging service expectations:
309         // - D-Bus error should be logged once for the D-Bus exceptions
310         // - N phase fault error should be logged once
311         MockErrorLogging& errorLogging = services.getMockErrorLogging();
312         EXPECT_CALL(errorLogging, logDBusError).Times(1);
313         EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
314 
315         // Set Sensors service expections:
316         // - startRail() and endRail() called 10 times
317         MockSensors& sensors = services.getMockSensors();
318         EXPECT_CALL(sensors, startRail).Times(10);
319         EXPECT_CALL(sensors, endRail).Times(10);
320     };
321 
322     // Monitor sensors and detect phase faults 10 times.  Verify errors logged.
323     {
324         // Create mock services.  Set expectations via lambda.
325         MockServices services{};
326         setExpectations(services);
327 
328         for (int i = 1; i <= 10; ++i)
329         {
330             device.monitorSensors(services, *system, *chassis);
331             device.detectPhaseFaults(services, *system, *chassis);
332         }
333     }
334 
335     // Clear error history
336     device.clearErrorHistory();
337 
338     // Monitor sensors and detect phase faults 10 more times.  Verify errors
339     // logged again.
340     {
341         // Create mock services.  Set expectations via lambda.
342         MockServices services{};
343         setExpectations(services);
344 
345         for (int i = 1; i <= 10; ++i)
346         {
347             device.monitorSensors(services, *system, *chassis);
348             device.detectPhaseFaults(services, *system, *chassis);
349         }
350     }
351 }
352 
353 TEST_F(DeviceTests, Close)
354 {
355     // Test where works: I2C interface is not open
356     {
357         // Create mock I2CInterface
358         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
359         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
360         EXPECT_CALL(*i2cInterface, close).Times(0);
361 
362         // Create mock services.  No logError should occur.
363         MockServices services{};
364         MockJournal& journal = services.getMockJournal();
365         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
366         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
367             .Times(0);
368 
369         // Create Device
370         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
371 
372         // Close Device
373         device.close(services);
374     }
375 
376     // Test where works: I2C interface is open
377     {
378         // Create mock I2CInterface
379         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
380         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
381         EXPECT_CALL(*i2cInterface, close).Times(1);
382 
383         // Create mock services.  No logError should occur.
384         MockServices services{};
385         MockJournal& journal = services.getMockJournal();
386         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
387         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
388             .Times(0);
389 
390         // Create Device
391         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
392 
393         // Close Device
394         device.close(services);
395     }
396 
397     // Test where fails: closing I2C interface fails
398     {
399         // Create mock I2CInterface
400         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
401         EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
402         EXPECT_CALL(*i2cInterface, close)
403             .Times(1)
404             .WillOnce(Throw(
405                 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
406 
407         // Create mock services.  Expect logError() and logI2CError() to be
408         // called.
409         MockServices services{};
410         MockErrorLogging& errorLogging = services.getMockErrorLogging();
411         MockJournal& journal = services.getMockJournal();
412         std::vector<std::string> expectedErrMessagesException{
413             "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
414         EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
415             .Times(1);
416         EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
417         EXPECT_CALL(errorLogging,
418                     logI2CError(Entry::Level::Notice, Ref(journal),
419                                 "/dev/i2c-1", 0x70, 0))
420             .Times(1);
421 
422         // Create Device
423         Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
424 
425         // Close Device
426         device.close(services);
427     }
428 }
429 
430 TEST_F(DeviceTests, Configure)
431 {
432     // Test where device is not present
433     {
434         // Create mock services.  No logging should occur.
435         MockServices services{};
436         MockJournal& journal = services.getMockJournal();
437         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
438         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
439 
440         // Create PresenceDetection.  Indicates device is not present.
441         std::unique_ptr<PresenceDetection> presenceDetection{};
442         {
443             auto action = std::make_unique<MockAction>();
444             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
445             std::vector<std::unique_ptr<Action>> actions{};
446             actions.emplace_back(std::move(action));
447             presenceDetection =
448                 std::make_unique<PresenceDetection>(std::move(actions));
449         }
450 
451         // Create Configuration.  Action inside it should not be executed.
452         std::unique_ptr<Configuration> configuration{};
453         {
454             std::optional<double> volts{};
455             auto action = std::make_unique<MockAction>();
456             EXPECT_CALL(*action, execute).Times(0);
457             std::vector<std::unique_ptr<Action>> actions{};
458             actions.emplace_back(std::move(action));
459             configuration =
460                 std::make_unique<Configuration>(volts, std::move(actions));
461         }
462 
463         // Create Device
464         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
465         Device device{"reg2",
466                       true,
467                       deviceInvPath,
468                       std::move(i2cInterface),
469                       std::move(presenceDetection),
470                       std::move(configuration)};
471 
472         // Call configure().  Should do nothing.
473         device.configure(services, *system, *chassis);
474     }
475 
476     // Test where Configuration and Rails were not specified in constructor
477     {
478         // Create mock services.  No logging should occur.
479         MockServices services{};
480         MockJournal& journal = services.getMockJournal();
481         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
482         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
483 
484         // Create Device
485         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
486         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
487 
488         // Call configure().
489         device.configure(services, *system, *chassis);
490     }
491 
492     // Test where Configuration and Rails were specified in constructor
493     {
494         std::vector<std::unique_ptr<Rail>> rails{};
495 
496         // Create mock services.  Expect logDebug() to be called.
497         // For the Device and both Rails, should execute the Configuration
498         // and log a debug message.
499         MockServices services{};
500         MockJournal& journal = services.getMockJournal();
501         EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
502         EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
503             .Times(1);
504         EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
505             .Times(1);
506         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
507 
508         // Create Rail vdd0
509         {
510             // Create Configuration for Rail
511             std::optional<double> volts{1.3};
512             auto action = std::make_unique<MockAction>();
513             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
514             std::vector<std::unique_ptr<Action>> actions{};
515             actions.emplace_back(std::move(action));
516             auto configuration =
517                 std::make_unique<Configuration>(volts, std::move(actions));
518 
519             // Create Rail
520             auto rail =
521                 std::make_unique<Rail>("vdd0", std::move(configuration));
522             rails.emplace_back(std::move(rail));
523         }
524 
525         // Create Rail vio0
526         {
527             // Create Configuration for Rail
528             std::optional<double> volts{3.2};
529             auto action = std::make_unique<MockAction>();
530             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
531             std::vector<std::unique_ptr<Action>> actions{};
532             actions.emplace_back(std::move(action));
533             auto configuration =
534                 std::make_unique<Configuration>(volts, std::move(actions));
535 
536             // Create Rail
537             auto rail =
538                 std::make_unique<Rail>("vio0", std::move(configuration));
539             rails.emplace_back(std::move(rail));
540         }
541 
542         // Create Configuration for Device
543         std::optional<double> volts{};
544         auto action = std::make_unique<MockAction>();
545         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
546         std::vector<std::unique_ptr<Action>> actions{};
547         actions.emplace_back(std::move(action));
548         auto configuration =
549             std::make_unique<Configuration>(volts, std::move(actions));
550 
551         // Create Device
552         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
553         std::unique_ptr<PresenceDetection> presenceDetection{};
554         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
555         Device device{"reg2",
556                       true,
557                       deviceInvPath,
558                       std::move(i2cInterface),
559                       std::move(presenceDetection),
560                       std::move(configuration),
561                       std::move(phaseFaultDetection),
562                       std::move(rails)};
563 
564         // Call configure().
565         device.configure(services, *system, *chassis);
566     }
567 }
568 
569 TEST_F(DeviceTests, DetectPhaseFaults)
570 {
571     // Test where device is not present
572     {
573         // Create mock services.  No errors should be logged.
574         MockServices services{};
575         MockJournal& journal = services.getMockJournal();
576         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
577         MockErrorLogging& errorLogging = services.getMockErrorLogging();
578         EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
579 
580         // Create PresenceDetection.  Indicates device is not present.
581         std::unique_ptr<PresenceDetection> presenceDetection{};
582         {
583             auto action = std::make_unique<MockAction>();
584             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
585             std::vector<std::unique_ptr<Action>> actions{};
586             actions.emplace_back(std::move(action));
587             presenceDetection =
588                 std::make_unique<PresenceDetection>(std::move(actions));
589         }
590 
591         // Create PhaseFaultDetection.  Action inside it should not be executed.
592         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
593         {
594             auto action = std::make_unique<MockAction>();
595             EXPECT_CALL(*action, execute).Times(0);
596             std::vector<std::unique_ptr<Action>> actions{};
597             actions.emplace_back(std::move(action));
598             phaseFaultDetection =
599                 std::make_unique<PhaseFaultDetection>(std::move(actions));
600         }
601 
602         // Create Device
603         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
604         std::unique_ptr<Configuration> configuration{};
605         Device device{"reg2",
606                       true,
607                       deviceInvPath,
608                       std::move(i2cInterface),
609                       std::move(presenceDetection),
610                       std::move(configuration),
611                       std::move(phaseFaultDetection)};
612 
613         // Call detectPhaseFaults() 5 times.  Should do nothing.
614         for (int i = 1; i <= 5; ++i)
615         {
616             device.detectPhaseFaults(services, *system, *chassis);
617         }
618     }
619 
620     // Test where PhaseFaultDetection was not specified in constructor
621     {
622         // Create mock services.  No errors should be logged.
623         MockServices services{};
624         MockJournal& journal = services.getMockJournal();
625         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
626         MockErrorLogging& errorLogging = services.getMockErrorLogging();
627         EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
628 
629         // Create Device
630         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
631         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
632 
633         // Call detectPhaseFaults() 5 times.  Should do nothing.
634         for (int i = 1; i <= 5; ++i)
635         {
636             device.detectPhaseFaults(services, *system, *chassis);
637         }
638     }
639 
640     // Test where PhaseFaultDetection was specified in constructor
641     {
642         // Create mock services with the following expectations:
643         // - 2 error messages in journal for N phase fault detected
644         // - 1 N phase fault error logged
645         MockServices services{};
646         MockJournal& journal = services.getMockJournal();
647         EXPECT_CALL(
648             journal,
649             logError("n phase fault detected in regulator reg2: count=1"))
650             .Times(1);
651         EXPECT_CALL(
652             journal,
653             logError("n phase fault detected in regulator reg2: count=2"))
654             .Times(1);
655         MockErrorLogging& errorLogging = services.getMockErrorLogging();
656         EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
657 
658         // Create PhaseFaultDetection
659         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
660         std::vector<std::unique_ptr<Action>> actions{};
661         actions.push_back(std::move(action));
662         auto phaseFaultDetection =
663             std::make_unique<PhaseFaultDetection>(std::move(actions));
664 
665         // Create Device
666         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
667         std::unique_ptr<PresenceDetection> presenceDetection{};
668         std::unique_ptr<Configuration> configuration{};
669         Device device{"reg2",
670                       true,
671                       deviceInvPath,
672                       std::move(i2cInterface),
673                       std::move(presenceDetection),
674                       std::move(configuration),
675                       std::move(phaseFaultDetection)};
676 
677         // Call detectPhaseFaults() 5 times
678         for (int i = 1; i <= 5; ++i)
679         {
680             device.detectPhaseFaults(services, *system, *chassis);
681         }
682     }
683 }
684 
685 TEST_F(DeviceTests, GetConfiguration)
686 {
687     // Test where Configuration was not specified in constructor
688     {
689         Device device{"vdd_reg", true, deviceInvPath,
690                       std::move(createI2CInterface())};
691         EXPECT_EQ(device.getConfiguration(), nullptr);
692     }
693 
694     // Test where Configuration was specified in constructor
695     {
696         std::unique_ptr<PresenceDetection> presenceDetection{};
697 
698         // Create Configuration
699         std::optional<double> volts{3.2};
700         std::vector<std::unique_ptr<Action>> actions{};
701         actions.push_back(std::make_unique<MockAction>());
702         actions.push_back(std::make_unique<MockAction>());
703         auto configuration =
704             std::make_unique<Configuration>(volts, std::move(actions));
705 
706         // Create Device
707         Device device{"vdd_reg",
708                       true,
709                       deviceInvPath,
710                       std::move(createI2CInterface()),
711                       std::move(presenceDetection),
712                       std::move(configuration)};
713         EXPECT_NE(device.getConfiguration(), nullptr);
714         EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
715         EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
716         EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
717     }
718 }
719 
720 TEST_F(DeviceTests, GetFRU)
721 {
722     Device device{"vdd_reg", true, deviceInvPath,
723                   std::move(createI2CInterface())};
724     EXPECT_EQ(device.getFRU(), deviceInvPath);
725 }
726 
727 TEST_F(DeviceTests, GetI2CInterface)
728 {
729     std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
730     i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
731     Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
732     EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
733 }
734 
735 TEST_F(DeviceTests, GetID)
736 {
737     Device device{"vdd_reg", false, deviceInvPath,
738                   std::move(createI2CInterface())};
739     EXPECT_EQ(device.getID(), "vdd_reg");
740 }
741 
742 TEST_F(DeviceTests, GetPhaseFaultDetection)
743 {
744     // Test where PhaseFaultDetection was not specified in constructor
745     {
746         Device device{"vdd_reg", true, deviceInvPath,
747                       std::move(createI2CInterface())};
748         EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
749     }
750 
751     // Test where PhaseFaultDetection was specified in constructor
752     {
753         // Create PhaseFaultDetection
754         std::vector<std::unique_ptr<Action>> actions{};
755         actions.push_back(std::make_unique<MockAction>());
756         auto phaseFaultDetection =
757             std::make_unique<PhaseFaultDetection>(std::move(actions));
758 
759         // Create Device
760         std::unique_ptr<PresenceDetection> presenceDetection{};
761         std::unique_ptr<Configuration> configuration{};
762         Device device{"vdd_reg",
763                       false,
764                       deviceInvPath,
765                       std::move(createI2CInterface()),
766                       std::move(presenceDetection),
767                       std::move(configuration),
768                       std::move(phaseFaultDetection)};
769         EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
770         EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
771     }
772 }
773 
774 TEST_F(DeviceTests, GetPresenceDetection)
775 {
776     // Test where PresenceDetection was not specified in constructor
777     {
778         Device device{"vdd_reg", true, deviceInvPath,
779                       std::move(createI2CInterface())};
780         EXPECT_EQ(device.getPresenceDetection(), nullptr);
781     }
782 
783     // Test where PresenceDetection was specified in constructor
784     {
785         // Create PresenceDetection
786         std::vector<std::unique_ptr<Action>> actions{};
787         actions.push_back(std::make_unique<MockAction>());
788         auto presenceDetection =
789             std::make_unique<PresenceDetection>(std::move(actions));
790 
791         // Create Device
792         Device device{"vdd_reg", false, deviceInvPath,
793                       std::move(createI2CInterface()),
794                       std::move(presenceDetection)};
795         EXPECT_NE(device.getPresenceDetection(), nullptr);
796         EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
797     }
798 }
799 
800 TEST_F(DeviceTests, GetRails)
801 {
802     // Test where no rails were specified in constructor
803     {
804         Device device{"vdd_reg", true, deviceInvPath,
805                       std::move(createI2CInterface())};
806         EXPECT_EQ(device.getRails().size(), 0);
807     }
808 
809     // Test where rails were specified in constructor
810     {
811         std::unique_ptr<PresenceDetection> presenceDetection{};
812         std::unique_ptr<Configuration> configuration{};
813         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
814 
815         // Create vector of Rail objects
816         std::vector<std::unique_ptr<Rail>> rails{};
817         rails.push_back(std::make_unique<Rail>("vdd0"));
818         rails.push_back(std::make_unique<Rail>("vdd1"));
819 
820         // Create Device
821         Device device{"vdd_reg",
822                       false,
823                       deviceInvPath,
824                       std::move(createI2CInterface()),
825                       std::move(presenceDetection),
826                       std::move(configuration),
827                       std::move(phaseFaultDetection),
828                       std::move(rails)};
829         EXPECT_EQ(device.getRails().size(), 2);
830         EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
831         EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
832     }
833 }
834 
835 TEST_F(DeviceTests, IsPresent)
836 {
837     // Test where PresenceDetection not specified in constructor
838     {
839         // Create Device
840         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
841         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
842 
843         // Create MockServices
844         MockServices services{};
845 
846         // Since no PresenceDetection defined, isPresent() should return true
847         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
848     }
849 
850     // Test where PresenceDetection was specified in constructor: Is present
851     {
852         // Create PresenceDetection.  Indicates device is present.
853         auto action = std::make_unique<MockAction>();
854         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
855         std::vector<std::unique_ptr<Action>> actions{};
856         actions.emplace_back(std::move(action));
857         auto presenceDetection =
858             std::make_unique<PresenceDetection>(std::move(actions));
859 
860         // Create Device
861         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
862         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
863                       std::move(presenceDetection)};
864 
865         // Create MockServices
866         MockServices services{};
867 
868         // PresenceDetection::execute() and isPresent() should return true
869         EXPECT_TRUE(device.isPresent(services, *system, *chassis));
870     }
871 
872     // Test where PresenceDetection was specified in constructor: Is not present
873     {
874         // Create PresenceDetection.  Indicates device is not present.
875         auto action = std::make_unique<MockAction>();
876         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
877         std::vector<std::unique_ptr<Action>> actions{};
878         actions.emplace_back(std::move(action));
879         auto presenceDetection =
880             std::make_unique<PresenceDetection>(std::move(actions));
881 
882         // Create Device
883         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
884         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
885                       std::move(presenceDetection)};
886 
887         // Create MockServices
888         MockServices services{};
889 
890         // PresenceDetection::execute() and isPresent() should return false
891         EXPECT_FALSE(device.isPresent(services, *system, *chassis));
892     }
893 }
894 
895 TEST_F(DeviceTests, IsRegulator)
896 {
897     Device device{"vdd_reg", false, deviceInvPath,
898                   std::move(createI2CInterface())};
899     EXPECT_EQ(device.isRegulator(), false);
900 }
901 
902 TEST_F(DeviceTests, MonitorSensors)
903 {
904     // Test where device is not present
905     {
906         // Create mock services.  No Sensors methods should be called.
907         MockServices services{};
908         MockSensors& sensors = services.getMockSensors();
909         EXPECT_CALL(sensors, startRail).Times(0);
910         EXPECT_CALL(sensors, setValue).Times(0);
911         EXPECT_CALL(sensors, endRail).Times(0);
912 
913         // Create SensorMonitoring.  Action inside it should not be executed.
914         std::unique_ptr<SensorMonitoring> sensorMonitoring{};
915         {
916             auto action = std::make_unique<MockAction>();
917             EXPECT_CALL(*action, execute).Times(0);
918             std::vector<std::unique_ptr<Action>> actions{};
919             actions.emplace_back(std::move(action));
920             sensorMonitoring =
921                 std::make_unique<SensorMonitoring>(std::move(actions));
922         }
923 
924         // Create Rail
925         std::unique_ptr<Configuration> configuration{};
926         auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
927                                            std::move(sensorMonitoring));
928 
929         // Create PresenceDetection.  Indicates device is not present.
930         std::unique_ptr<PresenceDetection> presenceDetection{};
931         {
932             auto action = std::make_unique<MockAction>();
933             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
934             std::vector<std::unique_ptr<Action>> actions{};
935             actions.emplace_back(std::move(action));
936             presenceDetection =
937                 std::make_unique<PresenceDetection>(std::move(actions));
938         }
939 
940         // Create Device
941         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
942         std::unique_ptr<Configuration> deviceConfiguration{};
943         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
944         std::vector<std::unique_ptr<Rail>> rails{};
945         rails.emplace_back(std::move(rail));
946         Device device{"reg2",
947                       true,
948                       deviceInvPath,
949                       std::move(i2cInterface),
950                       std::move(presenceDetection),
951                       std::move(deviceConfiguration),
952                       std::move(phaseFaultDetection),
953                       std::move(rails)};
954 
955         // Call monitorSensors().  Should do nothing.
956         device.monitorSensors(services, *system, *chassis);
957     }
958 
959     // Test where Rails were not specified in constructor
960     {
961         // Create mock services.  No Sensors methods should be called.
962         MockServices services{};
963         MockSensors& sensors = services.getMockSensors();
964         EXPECT_CALL(sensors, startRail).Times(0);
965         EXPECT_CALL(sensors, setValue).Times(0);
966         EXPECT_CALL(sensors, endRail).Times(0);
967 
968         // Create Device
969         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
970         Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
971 
972         // Call monitorSensors().  Should do nothing.
973         device.monitorSensors(services, *system, *chassis);
974     }
975 
976     // Test where Rails were specified in constructor
977     {
978         // Create mock services.  Set Sensors service expectations.
979         MockServices services{};
980         MockSensors& sensors = services.getMockSensors();
981         EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
982             .Times(1);
983         EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
984             .Times(1);
985         EXPECT_CALL(sensors, setValue).Times(0);
986         EXPECT_CALL(sensors, endRail(false)).Times(2);
987 
988         std::vector<std::unique_ptr<Rail>> rails{};
989 
990         // Create Rail vdd0
991         {
992             // Create SensorMonitoring for Rail
993             auto action = std::make_unique<MockAction>();
994             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
995             std::vector<std::unique_ptr<Action>> actions{};
996             actions.emplace_back(std::move(action));
997             auto sensorMonitoring =
998                 std::make_unique<SensorMonitoring>(std::move(actions));
999 
1000             // Create Rail
1001             std::unique_ptr<Configuration> configuration{};
1002             auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
1003                                                std::move(sensorMonitoring));
1004             rails.emplace_back(std::move(rail));
1005         }
1006 
1007         // Create Rail vio0
1008         {
1009             // Create SensorMonitoring for Rail
1010             auto action = std::make_unique<MockAction>();
1011             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
1012             std::vector<std::unique_ptr<Action>> actions{};
1013             actions.emplace_back(std::move(action));
1014             auto sensorMonitoring =
1015                 std::make_unique<SensorMonitoring>(std::move(actions));
1016 
1017             // Create Rail
1018             std::unique_ptr<Configuration> configuration{};
1019             auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
1020                                                std::move(sensorMonitoring));
1021             rails.emplace_back(std::move(rail));
1022         }
1023 
1024         // Create Device that contains Rails
1025         std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
1026         std::unique_ptr<PresenceDetection> presenceDetection{};
1027         std::unique_ptr<Configuration> configuration{};
1028         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
1029         Device device{"reg2",
1030                       true,
1031                       deviceInvPath,
1032                       std::move(i2cInterface),
1033                       std::move(presenceDetection),
1034                       std::move(configuration),
1035                       std::move(phaseFaultDetection),
1036                       std::move(rails)};
1037 
1038         // Call monitorSensors().  Should monitor sensors in both rails.
1039         device.monitorSensors(services, *system, *chassis);
1040     }
1041 }
1042