regulators: Create PresenceDetection class

Create C++ class that implements the 'presence_detection' element from
the JSON config file.  See presence_detection.md for more information.

The execute() method of this class will be implemented in a future
commit.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: Id6e1d66afe9179c92455d3f7b8f15bb54745f3eb
diff --git a/phosphor-regulators/src/presence_detection.hpp b/phosphor-regulators/src/presence_detection.hpp
new file mode 100644
index 0000000..23f416c
--- /dev/null
+++ b/phosphor-regulators/src/presence_detection.hpp
@@ -0,0 +1,104 @@
+/**
+ * Copyright © 2020 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "action.hpp"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace phosphor::power::regulators
+{
+
+/**
+ * @class PresenceDetection
+ *
+ * Specifies how to detect whether a device is present.
+ *
+ * Some devices are only present in certain system configurations.  For example:
+ * - A regulator is only present when a related processor or memory module is
+ *   present.
+ * - A system supports multiple storage backplane types, and the device only
+ *   exists on one of the backplanes.
+ *
+ * Device presence is detected by executing actions, such as
+ * ComparePresenceAction and CompareVPDAction.
+ *
+ * Device operations like configuration and sensor monitoring will only be
+ * performed if the actions indicate the device is present.
+ *
+ * Device presence will only be detected once per boot of the system.  Presence
+ * will be determined prior to the first device operation (such as
+ * configuration).  When the system is re-booted, presence will be re-detected.
+ * As a result, presence detection is not supported for devices that can be
+ * removed or added (hot-plugged) while the system is booted and running.
+ */
+class PresenceDetection
+{
+  public:
+    // Specify which compiler-generated methods we want
+    PresenceDetection() = delete;
+    PresenceDetection(const PresenceDetection&) = delete;
+    PresenceDetection(PresenceDetection&&) = delete;
+    PresenceDetection& operator=(const PresenceDetection&) = delete;
+    PresenceDetection& operator=(PresenceDetection&&) = delete;
+    ~PresenceDetection() = default;
+
+    /**
+     * Constructor.
+     *
+     * @param actions actions that detect whether the device is present
+     */
+    explicit PresenceDetection(std::vector<std::unique_ptr<Action>> actions) :
+        actions{std::move(actions)}
+    {
+    }
+
+    /**
+     * Executes the actions to detect whether the device is present.
+     *
+     * The return value of the last action indicates whether the device is
+     * present.  A return value of true means the device is present; false means
+     * the device is missing.
+     *
+     * @return true if device is present, false otherwise
+     */
+    bool execute()
+    {
+        // TODO: Create ActionEnvironment, execute actions, catch and handle any
+        // exceptions
+        return true;
+    }
+
+    /**
+     * Returns the actions that detect whether the device is present.
+     *
+     * @return actions
+     */
+    const std::vector<std::unique_ptr<Action>>& getActions() const
+    {
+        return actions;
+    }
+
+  private:
+    /**
+     * Actions that detect whether the device is present.
+     */
+    std::vector<std::unique_ptr<Action>> actions{};
+};
+
+} // namespace phosphor::power::regulators
diff --git a/phosphor-regulators/test/meson.build b/phosphor-regulators/test/meson.build
index 0220532..38c038d 100644
--- a/phosphor-regulators/test/meson.build
+++ b/phosphor-regulators/test/meson.build
@@ -9,6 +9,7 @@
     'id_map_tests.cpp',
     'pmbus_error_tests.cpp',
     'pmbus_utils_tests.cpp',
+    'presence_detection_tests.cpp',
     'rail_tests.cpp',
     'rule_tests.cpp',
     'write_verification_error_tests.cpp',
diff --git a/phosphor-regulators/test/presence_detection_tests.cpp b/phosphor-regulators/test/presence_detection_tests.cpp
new file mode 100644
index 0000000..7f3c10f
--- /dev/null
+++ b/phosphor-regulators/test/presence_detection_tests.cpp
@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2020 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "action.hpp"
+#include "mock_action.hpp"
+#include "presence_detection.hpp"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+using namespace phosphor::power::regulators;
+
+TEST(PresenceDetectionTests, Constructor)
+{
+    std::vector<std::unique_ptr<Action>> actions{};
+    actions.push_back(std::make_unique<MockAction>());
+
+    PresenceDetection presenceDetection(std::move(actions));
+    EXPECT_EQ(presenceDetection.getActions().size(), 1);
+}
+
+TEST(PresenceDetectionTests, Execute)
+{
+    // TODO: Implement test when execute() function is done
+}
+
+TEST(PresenceDetectionTests, GetActions)
+{
+    std::vector<std::unique_ptr<Action>> actions{};
+
+    MockAction* action1 = new MockAction{};
+    actions.push_back(std::unique_ptr<MockAction>{action1});
+
+    MockAction* action2 = new MockAction{};
+    actions.push_back(std::unique_ptr<MockAction>{action2});
+
+    PresenceDetection presenceDetection(std::move(actions));
+    EXPECT_EQ(presenceDetection.getActions().size(), 2);
+    EXPECT_EQ(presenceDetection.getActions()[0].get(), action1);
+    EXPECT_EQ(presenceDetection.getActions()[1].get(), action2);
+}