regulators: Clear phase fault history in Device

Enhance the clearErrorHistory() method of the Device class to clear
phase fault error history.

Update the gtest test case to exercise the modified code.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I109932c0f4812bb36af05ac24e47a561270b4fcc
diff --git a/phosphor-regulators/src/device.cpp b/phosphor-regulators/src/device.cpp
index bde41cc..7d80851 100644
--- a/phosphor-regulators/src/device.cpp
+++ b/phosphor-regulators/src/device.cpp
@@ -50,6 +50,12 @@
 
 void Device::clearErrorHistory()
 {
+    // Clear error history in phase fault detection, if defined
+    if (phaseFaultDetection)
+    {
+        phaseFaultDetection->clearErrorHistory();
+    }
+
     // Clear error history in each rail
     for (std::unique_ptr<Rail>& rail : rails)
     {
diff --git a/phosphor-regulators/test/device_tests.cpp b/phosphor-regulators/test/device_tests.cpp
index 5a7e853..5d9a0e4 100644
--- a/phosphor-regulators/test/device_tests.cpp
+++ b/phosphor-regulators/test/device_tests.cpp
@@ -243,24 +243,36 @@
 TEST_F(DeviceTests, ClearErrorHistory)
 {
     // Create SensorMonitoring.  Will fail with a DBus exception.
-    auto action = std::make_unique<MockAction>();
-    EXPECT_CALL(*action, execute)
-        .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
-    std::vector<std::unique_ptr<Action>> actions{};
-    actions.emplace_back(std::move(action));
-    auto sensorMonitoring =
-        std::make_unique<SensorMonitoring>(std::move(actions));
+    std::unique_ptr<SensorMonitoring> sensorMonitoring{};
+    {
+        auto action = std::make_unique<MockAction>();
+        EXPECT_CALL(*action, execute)
+            .WillRepeatedly(Throw(TestSDBusError{"DBus Error"}));
+        std::vector<std::unique_ptr<Action>> actions{};
+        actions.emplace_back(std::move(action));
+        sensorMonitoring =
+            std::make_unique<SensorMonitoring>(std::move(actions));
+    }
 
     // Create Rail
     std::unique_ptr<Configuration> configuration{};
-    auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
+    auto rail = std::make_unique<Rail>("vdd", std::move(configuration),
                                        std::move(sensorMonitoring));
 
-    // Create Device that contains Rail
+    // Create PhaseFaultDetection.  Will log an N phase fault.
+    std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
+    {
+        auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
+        std::vector<std::unique_ptr<Action>> actions{};
+        actions.emplace_back(std::move(action));
+        phaseFaultDetection =
+            std::make_unique<PhaseFaultDetection>(std::move(actions));
+    }
+
+    // Create Device
     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
     std::unique_ptr<PresenceDetection> presenceDetection{};
     std::unique_ptr<Configuration> deviceConfiguration{};
-    std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
     std::vector<std::unique_ptr<Rail>> rails{};
     rails.emplace_back(std::move(rail));
     Device device{"reg2",
@@ -272,40 +284,69 @@
                   std::move(phaseFaultDetection),
                   std::move(rails)};
 
-    // Create mock services
-    MockServices services{};
+    // Create lambda that sets MockServices expectations.  The lambda allows us
+    // to set the same expectations twice without duplicate code.
+    auto setExpectations = [](MockServices& services) {
+        // Set Journal service expectations:
+        // - 3 error messages for D-Bus errors
+        // - 3 error messages for inability to monitor sensors
+        // - 2 error messages for the N phase fault
+        MockJournal& journal = services.getMockJournal();
+        EXPECT_CALL(journal, logError(std::vector<std::string>{"DBus Error"}))
+            .Times(3);
+        EXPECT_CALL(journal, logError("Unable to monitor sensors for rail vdd"))
+            .Times(3);
+        EXPECT_CALL(
+            journal,
+            logError("n phase fault detected in regulator reg2: count=1"))
+            .Times(1);
+        EXPECT_CALL(
+            journal,
+            logError("n phase fault detected in regulator reg2: count=2"))
+            .Times(1);
 
-    // Expect Sensors service to be called 5+5=10 times
-    MockSensors& sensors = services.getMockSensors();
-    EXPECT_CALL(sensors, startRail).Times(10);
-    EXPECT_CALL(sensors, setValue).Times(0);
-    EXPECT_CALL(sensors, endRail).Times(10);
+        // Set ErrorLogging service expectations:
+        // - D-Bus error should be logged once for the D-Bus exceptions
+        // - N phase fault error should be logged once
+        MockErrorLogging& errorLogging = services.getMockErrorLogging();
+        EXPECT_CALL(errorLogging, logDBusError).Times(1);
+        EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
 
-    // Expect Journal service to be called 3+3=6 times to log error messages
-    MockJournal& journal = services.getMockJournal();
-    EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
-        .Times(6);
-    EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
+        // Set Sensors service expections:
+        // - startRail() and endRail() called 5 times
+        MockSensors& sensors = services.getMockSensors();
+        EXPECT_CALL(sensors, startRail).Times(5);
+        EXPECT_CALL(sensors, endRail).Times(5);
+    };
 
-    // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
-    MockErrorLogging& errorLogging = services.getMockErrorLogging();
-    EXPECT_CALL(errorLogging, logDBusError).Times(2);
-
-    // Monitor sensors 5 times.  Should fail every time, write to journal 3
-    // times, and log one error.
-    for (int i = 1; i <= 5; ++i)
+    // Monitor sensors and detect phase faults 5 times.  Verify errors logged.
     {
-        device.monitorSensors(services, *system, *chassis);
+        // Create mock services.  Set expectations via lambda.
+        MockServices services{};
+        setExpectations(services);
+
+        for (int i = 1; i <= 5; ++i)
+        {
+            device.monitorSensors(services, *system, *chassis);
+            device.detectPhaseFaults(services, *system, *chassis);
+        }
     }
 
     // Clear error history
     device.clearErrorHistory();
 
-    // Monitor sensors 5 times again.  Should fail every time, write to journal
-    // 3 times, and log one error.
-    for (int i = 1; i <= 5; ++i)
+    // Monitor sensors and detect phase faults 5 more times.  Verify errors
+    // logged again.
     {
-        device.monitorSensors(services, *system, *chassis);
+        // Create mock services.  Set expectations via lambda.
+        MockServices services{};
+        setExpectations(services);
+
+        for (int i = 1; i <= 5; ++i)
+        {
+            device.monitorSensors(services, *system, *chassis);
+            device.detectPhaseFaults(services, *system, *chassis);
+        }
     }
 }