Enhance regulators Rule class

Enhance the regulators Rule class by adding a vector of actions and an
execute() method.

Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I09300b7345110fbce8b3a794c8f77a8d234ff538
diff --git a/phosphor-regulators/test/actions/action_environment_tests.cpp b/phosphor-regulators/test/actions/action_environment_tests.cpp
index eddce87..ff13c83 100644
--- a/phosphor-regulators/test/actions/action_environment_tests.cpp
+++ b/phosphor-regulators/test/actions/action_environment_tests.cpp
@@ -117,7 +117,8 @@
 {
     // Create IDMap
     IDMap idMap{};
-    Rule setVoltageRule{"set_voltage_rule"};
+    Rule setVoltageRule{"set_voltage_rule",
+                        std::vector<std::unique_ptr<Action>>{}};
     idMap.addRule(setVoltageRule);
 
     ActionEnvironment env{idMap, ""};
diff --git a/phosphor-regulators/test/id_map_tests.cpp b/phosphor-regulators/test/id_map_tests.cpp
index 5d47d7d..fae5fff 100644
--- a/phosphor-regulators/test/id_map_tests.cpp
+++ b/phosphor-regulators/test/id_map_tests.cpp
@@ -92,7 +92,7 @@
 
     // Create rule
     std::string id{"set_voltage_rule"};
-    Rule rule{id};
+    Rule rule{id, std::vector<std::unique_ptr<Action>>{}};
 
     // Verify rule is not initially in map
     EXPECT_THROW(idMap.getRule(id), std::invalid_argument);
@@ -198,7 +198,7 @@
 
     // Add a rule to the map
     std::string id{"set_voltage_rule"};
-    Rule rule{id};
+    Rule rule{id, std::vector<std::unique_ptr<Action>>{}};
     idMap.addRule(rule);
 
     // Test where ID found in map
diff --git a/phosphor-regulators/test/rule_tests.cpp b/phosphor-regulators/test/rule_tests.cpp
index a350238..f6e5d82 100644
--- a/phosphor-regulators/test/rule_tests.cpp
+++ b/phosphor-regulators/test/rule_tests.cpp
@@ -13,20 +13,107 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "action.hpp"
+#include "action_environment.hpp"
+#include "id_map.hpp"
+#include "mock_action.hpp"
 #include "rule.hpp"
 
+#include <exception>
+#include <memory>
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 using namespace phosphor::power::regulators;
 
+using ::testing::Return;
+using ::testing::Throw;
+
 TEST(RuleTests, Constructor)
 {
-    Rule rule("set_voltage_rule");
+    // Build vector of actions
+    std::vector<std::unique_ptr<Action>> actions{};
+    actions.push_back(std::make_unique<MockAction>());
+    actions.push_back(std::make_unique<MockAction>());
+
+    // Create rule and verify data members
+    Rule rule("set_voltage_rule", std::move(actions));
     EXPECT_EQ(rule.getID(), "set_voltage_rule");
+    EXPECT_EQ(rule.getActions().size(), 2);
+}
+
+TEST(RuleTests, Execute)
+{
+    // Create ActionEnvironment
+    IDMap idMap{};
+    ActionEnvironment env{idMap, ""};
+
+    // Test where an action throws an exception
+    try
+    {
+        std::vector<std::unique_ptr<Action>> actions{};
+        std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
+        EXPECT_CALL(*action, execute)
+            .Times(1)
+            .WillOnce(Throw(std::logic_error{"Communication error"}));
+        actions.push_back(std::move(action));
+
+        Rule rule("set_voltage_rule", std::move(actions));
+        rule.execute(env);
+        ADD_FAILURE() << "Should not have reached this line.";
+    }
+    catch (const std::exception& error)
+    {
+        EXPECT_STREQ(error.what(), "Communication error");
+    }
+
+    // Test where all actions are executed
+    try
+    {
+        std::vector<std::unique_ptr<Action>> actions{};
+        std::unique_ptr<MockAction> action;
+
+        // First action will return true
+        action = std::make_unique<MockAction>();
+        EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
+        actions.push_back(std::move(action));
+
+        // Second action will return false
+        action = std::make_unique<MockAction>();
+        EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
+        actions.push_back(std::move(action));
+
+        Rule rule("set_voltage_rule", std::move(actions));
+        EXPECT_EQ(rule.execute(env), false);
+    }
+    catch (const std::exception& error)
+    {
+        ADD_FAILURE() << "Should not have caught exception.";
+    }
+}
+
+TEST(RuleTests, 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});
+
+    Rule rule("set_voltage_rule", std::move(actions));
+    EXPECT_EQ(rule.getActions().size(), 2);
+    EXPECT_EQ(rule.getActions()[0].get(), action1);
+    EXPECT_EQ(rule.getActions()[1].get(), action2);
 }
 
 TEST(RuleTests, GetID)
 {
-    Rule rule("read_sensor_values");
+    Rule rule("read_sensor_values", std::vector<std::unique_ptr<Action>>{});
     EXPECT_EQ(rule.getID(), "read_sensor_values");
 }