regulators: Clear cached hardware data during boot

Clear cached data about hardware devices when the system is powering on
(booting).

While the system was powered off, hardware devices containing voltage
regulators could have been added, removed, or replaced.  Cached hardware
data might now be invalid.

Tested:
* Ran automated test cases
* Verified that cached data is cleared without errors during boot
  * When config file was found and loaded
  * When no config file was found

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: Ief45fe32ddcb122847d201e89ca1267526a87e3c
diff --git a/phosphor-regulators/test/chassis_tests.cpp b/phosphor-regulators/test/chassis_tests.cpp
index 451e137..601bf3f 100644
--- a/phosphor-regulators/test/chassis_tests.cpp
+++ b/phosphor-regulators/test/chassis_tests.cpp
@@ -111,6 +111,47 @@
     EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
 }
 
+TEST(ChassisTests, ClearCache)
+{
+    // Create PresenceDetection
+    std::vector<std::unique_ptr<Action>> actions{};
+    std::unique_ptr<PresenceDetection> presenceDetection =
+        std::make_unique<PresenceDetection>(std::move(actions));
+    PresenceDetection* presenceDetectionPtr = presenceDetection.get();
+
+    // Create Device that contains PresenceDetection
+    std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+    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));
+    Device* devicePtr = device.get();
+
+    // 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, 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)};
+
+    // Cache presence value in PresenceDetection
+    MockServices services{};
+    presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr);
+    EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
+
+    // Clear cached data in Chassis
+    chassisPtr->clearCache();
+
+    // Verify presence value no longer cached in PresenceDetection
+    EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
+}
+
 TEST(ChassisTests, CloseDevices)
 {
     // Test where no devices were specified in constructor
diff --git a/phosphor-regulators/test/device_tests.cpp b/phosphor-regulators/test/device_tests.cpp
index ad2b9c2..717bb9d 100644
--- a/phosphor-regulators/test/device_tests.cpp
+++ b/phosphor-regulators/test/device_tests.cpp
@@ -151,6 +151,65 @@
     EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
 }
 
+TEST(DeviceTests, ClearCache)
+{
+    // Test where Device does not contain a PresenceDetection object
+    try
+    {
+        Device device{
+            "vdd_reg", false,
+            "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
+            std::move(createI2CInterface())};
+        device.clearCache();
+    }
+    catch (...)
+    {
+        ADD_FAILURE() << "Should not have caught exception.";
+    }
+
+    // Test where Device contains a PresenceDetection object
+    {
+        // Create PresenceDetection
+        std::vector<std::unique_ptr<Action>> actions{};
+        std::unique_ptr<PresenceDetection> presenceDetection =
+            std::make_unique<PresenceDetection>(std::move(actions));
+        PresenceDetection* presenceDetectionPtr = presenceDetection.get();
+
+        // Create Device
+        std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+        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));
+        Device* devicePtr = device.get();
+
+        // 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, 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)};
+
+        // Cache presence value in PresenceDetection
+        MockServices services{};
+        presenceDetectionPtr->execute(services, system, *chassisPtr,
+                                      *devicePtr);
+        EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
+
+        // Clear cached data in Device
+        devicePtr->clearCache();
+
+        // Verify presence value no longer cached in PresenceDetection
+        EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
+    }
+}
+
 TEST(DeviceTests, Close)
 {
     // Test where works: I2C interface is not open
diff --git a/phosphor-regulators/test/system_tests.cpp b/phosphor-regulators/test/system_tests.cpp
index d5b5b1a..b71155c 100644
--- a/phosphor-regulators/test/system_tests.cpp
+++ b/phosphor-regulators/test/system_tests.cpp
@@ -66,6 +66,47 @@
     EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule");
 }
 
+TEST(SystemTests, ClearCache)
+{
+    // Create PresenceDetection
+    std::vector<std::unique_ptr<Action>> actions{};
+    std::unique_ptr<PresenceDetection> presenceDetection =
+        std::make_unique<PresenceDetection>(std::move(actions));
+    PresenceDetection* presenceDetectionPtr = presenceDetection.get();
+
+    // Create Device that contains PresenceDetection
+    std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
+    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));
+    Device* devicePtr = device.get();
+
+    // 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, 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)};
+
+    // Cache presence value in PresenceDetection
+    MockServices services{};
+    presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr);
+    EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
+
+    // Clear cached data in System
+    system.clearCache();
+
+    // Verify presence value no longer cached in PresenceDetection
+    EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
+}
+
 TEST(SystemTests, CloseDevices)
 {
     // Specify an empty rules vector