regulators: Add clearErrorHistory to Chassis class

Add a clearErrorHistory() method to the Chassis class.  The method
should clear all data on previously logged errors.  If the error occurs
again in the future, it will be logged again.

This method is normally called when the system is being powered on.  For
code that runs repeatedly, errors are only logged once per boot.

When the system is powered off, hardware may be replaced that fixes the
problem.  Thus, errors are cleared during power on.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I2b5c70004678fa48e28be48775cb6491a4d52090
diff --git a/phosphor-regulators/test/chassis_tests.cpp b/phosphor-regulators/test/chassis_tests.cpp
index def281c..69968a0 100644
--- a/phosphor-regulators/test/chassis_tests.cpp
+++ b/phosphor-regulators/test/chassis_tests.cpp
@@ -20,6 +20,7 @@
 #include "i2c_interface.hpp"
 #include "id_map.hpp"
 #include "mock_action.hpp"
+#include "mock_error_logging.hpp"
 #include "mock_journal.hpp"
 #include "mock_sensors.hpp"
 #include "mock_services.hpp"
@@ -30,6 +31,7 @@
 #include "sensor_monitoring.hpp"
 #include "sensors.hpp"
 #include "system.hpp"
+#include "test_sdbus_error.hpp"
 #include "test_utils.hpp"
 
 #include <memory>
@@ -46,6 +48,7 @@
 
 using ::testing::A;
 using ::testing::Return;
+using ::testing::Throw;
 using ::testing::TypedEq;
 
 // Default chassis inventory path
@@ -161,6 +164,85 @@
     EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
 }
 
+TEST(ChassisTests, ClearErrorHistory)
+{
+    // Create SensorMonitoring.  Will fail with a DBus exception.
+    std::unique_ptr<MockAction> 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));
+    std::unique_ptr<SensorMonitoring> sensorMonitoring =
+        std::make_unique<SensorMonitoring>(std::move(actions));
+
+    // Create Rail
+    std::unique_ptr<Configuration> configuration{};
+    std::unique_ptr<Rail> rail = std::make_unique<Rail>(
+        "vddr1", std::move(configuration), std::move(sensorMonitoring));
+
+    // Create Device that contains Rail
+    std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
+        std::make_unique<i2c::MockedI2CInterface>();
+    std::unique_ptr<PresenceDetection> presenceDetection{};
+    std::unique_ptr<Configuration> deviceConfiguration{};
+    std::vector<std::unique_ptr<Rail>> rails{};
+    rails.emplace_back(std::move(rail));
+    std::unique_ptr<Device> device = std::make_unique<Device>(
+        "reg1", true,
+        "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
+        std::move(i2cInterface), std::move(presenceDetection),
+        std::move(deviceConfiguration), std::move(rails));
+
+    // Create Chassis that contains Device
+    std::vector<std::unique_ptr<Device>> devices{};
+    devices.emplace_back(std::move(device));
+    std::unique_ptr<Chassis> chassis =
+        std::make_unique<Chassis>(1, defaultInventoryPath, std::move(devices));
+    Chassis* chassisPtr = chassis.get();
+
+    // Create System that contains Chassis
+    std::vector<std::unique_ptr<Rule>> rules{};
+    std::vector<std::unique_ptr<Chassis>> chassisVec{};
+    chassisVec.emplace_back(std::move(chassis));
+    System system{std::move(rules), std::move(chassisVec)};
+
+    // Create mock services
+    MockServices services{};
+
+    // 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);
+
+    // 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);
+
+    // 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)
+    {
+        chassisPtr->monitorSensors(services, system);
+    }
+
+    // Clear error history
+    chassisPtr->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)
+    {
+        chassisPtr->monitorSensors(services, system);
+    }
+}
+
 TEST(ChassisTests, CloseDevices)
 {
     // Test where no devices were specified in constructor