1 /**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "action.hpp"
17 #include "action_environment.hpp"
18 #include "device.hpp"
19 #include "id_map.hpp"
20 #include "mock_action.hpp"
21 #include "mock_services.hpp"
22 #include "rule.hpp"
23 #include "run_rule_action.hpp"
24
25 #include <exception>
26 #include <memory>
27 #include <stdexcept>
28 #include <utility>
29 #include <vector>
30
31 #include <gmock/gmock.h>
32 #include <gtest/gtest.h>
33
34 using namespace phosphor::power::regulators;
35
36 using ::testing::Return;
37 using ::testing::Throw;
38
TEST(RunRuleActionTests,Constructor)39 TEST(RunRuleActionTests, Constructor)
40 {
41 RunRuleAction action{"set_voltage_rule"};
42 EXPECT_EQ(action.getRuleID(), "set_voltage_rule");
43 }
44
TEST(RunRuleActionTests,Execute)45 TEST(RunRuleActionTests, Execute)
46 {
47 // Test where rule ID is not in the IDMap/ActionEnvironment
48 try
49 {
50 IDMap idMap{};
51 MockServices services{};
52 ActionEnvironment env{idMap, "", services};
53 RunRuleAction runRuleAction{"set_voltage_rule"};
54 runRuleAction.execute(env);
55 ADD_FAILURE() << "Should not have reached this line.";
56 }
57 catch (const std::invalid_argument& ia_error)
58 {
59 EXPECT_STREQ(ia_error.what(),
60 "Unable to find rule with ID \"set_voltage_rule\"");
61 }
62 catch (const std::exception& error)
63 {
64 ADD_FAILURE() << "Should not have caught exception.";
65 }
66
67 // Test where a rule action throws an exception
68 try
69 {
70 // Create rule with action that throws an exception
71 std::vector<std::unique_ptr<Action>> actions{};
72 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
73 EXPECT_CALL(*action, execute)
74 .Times(1)
75 .WillOnce(Throw(std::logic_error{"Communication error"}));
76 actions.push_back(std::move(action));
77 Rule rule("exception_rule", std::move(actions));
78
79 // Create ActionEnvironment
80 IDMap idMap{};
81 idMap.addRule(rule);
82 MockServices services{};
83 ActionEnvironment env{idMap, "", services};
84
85 // Create RunRuleAction
86 RunRuleAction runRuleAction{"exception_rule"};
87 runRuleAction.execute(env);
88 ADD_FAILURE() << "Should not have reached this line.";
89 }
90 catch (const std::exception& error)
91 {
92 EXPECT_STREQ(error.what(), "Communication error");
93 }
94
95 // Test where rule calls itself and results in infinite recursion
96 try
97 {
98 // Create rule that calls itself
99 std::vector<std::unique_ptr<Action>> actions{};
100 actions.push_back(std::make_unique<RunRuleAction>("infinite_rule"));
101 Rule rule("infinite_rule", std::move(actions));
102
103 // Create ActionEnvironment
104 IDMap idMap{};
105 idMap.addRule(rule);
106 MockServices services{};
107 ActionEnvironment env{idMap, "", services};
108
109 // Create RunRuleAction
110 RunRuleAction runRuleAction{"infinite_rule"};
111 runRuleAction.execute(env);
112 ADD_FAILURE() << "Should not have reached this line.";
113 }
114 catch (const std::runtime_error& r_error)
115 {
116 EXPECT_STREQ(r_error.what(),
117 "Maximum rule depth exceeded by rule infinite_rule.");
118 }
119 catch (const std::exception& error)
120 {
121 ADD_FAILURE() << "Should not have caught exception.";
122 }
123
124 // Test where last action returns false
125 try
126 {
127 // Create rule with two actions. Last action returns false.
128 std::vector<std::unique_ptr<Action>> actions{};
129 std::unique_ptr<MockAction> action;
130
131 action = std::make_unique<MockAction>();
132 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
133 actions.push_back(std::move(action));
134
135 action = std::make_unique<MockAction>();
136 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
137 actions.push_back(std::move(action));
138
139 Rule rule("set_voltage_rule", std::move(actions));
140
141 // Create ActionEnvironment
142 IDMap idMap{};
143 idMap.addRule(rule);
144 MockServices services{};
145 ActionEnvironment env{idMap, "", services};
146
147 // Create RunRuleAction
148 RunRuleAction runRuleAction{"set_voltage_rule"};
149 EXPECT_EQ(runRuleAction.execute(env), false);
150 EXPECT_EQ(env.getRuleDepth(), 0);
151 }
152 catch (const std::exception& error)
153 {
154 ADD_FAILURE() << "Should not have caught exception.";
155 }
156
157 // Test where last action returns true
158 try
159 {
160 // Create rule with two actions. Last action returns true.
161 std::vector<std::unique_ptr<Action>> actions{};
162 std::unique_ptr<MockAction> action;
163
164 action = std::make_unique<MockAction>();
165 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
166 actions.push_back(std::move(action));
167
168 action = std::make_unique<MockAction>();
169 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
170 actions.push_back(std::move(action));
171
172 Rule rule("set_voltage_rule", std::move(actions));
173
174 // Create ActionEnvironment
175 IDMap idMap{};
176 idMap.addRule(rule);
177 MockServices services{};
178 ActionEnvironment env{idMap, "", services};
179
180 // Create RunRuleAction
181 RunRuleAction runRuleAction{"set_voltage_rule"};
182 EXPECT_EQ(runRuleAction.execute(env), true);
183 EXPECT_EQ(env.getRuleDepth(), 0);
184 }
185 catch (const std::exception& error)
186 {
187 ADD_FAILURE() << "Should not have caught exception.";
188 }
189 }
190
TEST(RunRuleActionTests,GetRuleID)191 TEST(RunRuleActionTests, GetRuleID)
192 {
193 RunRuleAction action{"read_sensors_rule"};
194 EXPECT_EQ(action.getRuleID(), "read_sensors_rule");
195 }
196
TEST(RunRuleActionTests,ToString)197 TEST(RunRuleActionTests, ToString)
198 {
199 RunRuleAction action{"set_voltage_rule"};
200 EXPECT_EQ(action.toString(), "run_rule: set_voltage_rule");
201 }
202