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 "id_map.hpp"
19 #include "if_action.hpp"
20 #include "mock_action.hpp"
21 #include "mock_services.hpp"
22
23 #include <exception>
24 #include <memory>
25 #include <stdexcept>
26 #include <utility>
27 #include <vector>
28
29 #include <gmock/gmock.h>
30 #include <gtest/gtest.h>
31
32 using namespace phosphor::power::regulators;
33
34 using ::testing::Return;
35 using ::testing::Throw;
36
TEST(IfActionTests,Constructor)37 TEST(IfActionTests, Constructor)
38 {
39 // Test where else clause is not specified
40 {
41 std::unique_ptr<Action> conditionAction =
42 std::make_unique<MockAction>();
43
44 std::vector<std::unique_ptr<Action>> thenActions{};
45 thenActions.push_back(std::make_unique<MockAction>());
46 thenActions.push_back(std::make_unique<MockAction>());
47
48 IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
49 EXPECT_NE(ifAction.getConditionAction().get(), nullptr);
50 EXPECT_EQ(ifAction.getThenActions().size(), 2);
51 EXPECT_EQ(ifAction.getElseActions().size(), 0);
52 }
53
54 // Test where else clause is specified
55 {
56 std::unique_ptr<Action> conditionAction =
57 std::make_unique<MockAction>();
58
59 std::vector<std::unique_ptr<Action>> thenActions{};
60 thenActions.push_back(std::make_unique<MockAction>());
61 thenActions.push_back(std::make_unique<MockAction>());
62
63 std::vector<std::unique_ptr<Action>> elseActions{};
64 elseActions.push_back(std::make_unique<MockAction>());
65
66 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
67 std::move(elseActions)};
68 EXPECT_NE(ifAction.getConditionAction().get(), nullptr);
69 EXPECT_EQ(ifAction.getThenActions().size(), 2);
70 EXPECT_EQ(ifAction.getElseActions().size(), 1);
71 }
72 }
73
TEST(IfActionTests,Execute)74 TEST(IfActionTests, Execute)
75 {
76 // Create ActionEnvironment
77 IDMap idMap{};
78 MockServices services{};
79 ActionEnvironment env{idMap, "", services};
80
81 // Test where action throws an exception
82 try
83 {
84 // Create condition action that will return true
85 std::unique_ptr<MockAction> conditionAction =
86 std::make_unique<MockAction>();
87 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
88
89 // Create vector of actions for then clause
90 std::vector<std::unique_ptr<Action>> thenActions{};
91 std::unique_ptr<MockAction> thenAction;
92
93 // First then action will throw an exception
94 thenAction = std::make_unique<MockAction>();
95 EXPECT_CALL(*thenAction, execute)
96 .Times(1)
97 .WillOnce(Throw(std::logic_error{"Communication error"}));
98 thenActions.push_back(std::move(thenAction));
99
100 // Second then action should not get executed
101 thenAction = std::make_unique<MockAction>();
102 EXPECT_CALL(*thenAction, execute).Times(0);
103 thenActions.push_back(std::move(thenAction));
104
105 IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
106 ifAction.execute(env);
107 ADD_FAILURE() << "Should not have reached this line.";
108 }
109 catch (const std::exception& error)
110 {
111 EXPECT_STREQ(error.what(), "Communication error");
112 }
113
114 // Test where condition is true: then clause returns true
115 try
116 {
117 // Create condition action that will return true
118 std::unique_ptr<MockAction> conditionAction =
119 std::make_unique<MockAction>();
120 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
121
122 // Create vector of actions for then clause: last action returns true
123 std::vector<std::unique_ptr<Action>> thenActions{};
124 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
125 EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(true));
126 thenActions.push_back(std::move(thenAction));
127
128 // Create vector of actions for else clause: should not be executed
129 std::vector<std::unique_ptr<Action>> elseActions{};
130 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
131 EXPECT_CALL(*elseAction, execute).Times(0);
132 elseActions.push_back(std::move(elseAction));
133
134 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
135 std::move(elseActions)};
136 EXPECT_EQ(ifAction.execute(env), true);
137 }
138 catch (const std::exception& error)
139 {
140 ADD_FAILURE() << "Should not have caught exception.";
141 }
142
143 // Test where condition is true: then clause returns false
144 try
145 {
146 // Create condition action that will return true
147 std::unique_ptr<MockAction> conditionAction =
148 std::make_unique<MockAction>();
149 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
150
151 // Create vector of actions for then clause: last action returns false
152 std::vector<std::unique_ptr<Action>> thenActions{};
153 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
154 EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(false));
155 thenActions.push_back(std::move(thenAction));
156
157 // Create vector of actions for else clause: should not be executed
158 std::vector<std::unique_ptr<Action>> elseActions{};
159 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
160 EXPECT_CALL(*elseAction, execute).Times(0);
161 elseActions.push_back(std::move(elseAction));
162
163 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
164 std::move(elseActions)};
165 EXPECT_EQ(ifAction.execute(env), false);
166 }
167 catch (const std::exception& error)
168 {
169 ADD_FAILURE() << "Should not have caught exception.";
170 }
171
172 // Test where condition is false: else clause returns true
173 try
174 {
175 // Create condition action that will return false
176 std::unique_ptr<MockAction> conditionAction =
177 std::make_unique<MockAction>();
178 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
179
180 // Create vector of actions for then clause: should not be executed
181 std::vector<std::unique_ptr<Action>> thenActions{};
182 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
183 EXPECT_CALL(*thenAction, execute).Times(0);
184 thenActions.push_back(std::move(thenAction));
185
186 // Create vector of actions for else clause: last action returns true
187 std::vector<std::unique_ptr<Action>> elseActions{};
188 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
189 EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(true));
190 elseActions.push_back(std::move(elseAction));
191
192 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
193 std::move(elseActions)};
194 EXPECT_EQ(ifAction.execute(env), true);
195 }
196 catch (const std::exception& error)
197 {
198 ADD_FAILURE() << "Should not have caught exception.";
199 }
200
201 // Test where condition is false: else clause returns false
202 try
203 {
204 // Create condition action that will return false
205 std::unique_ptr<MockAction> conditionAction =
206 std::make_unique<MockAction>();
207 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
208
209 // Create vector of actions for then clause: should not be executed
210 std::vector<std::unique_ptr<Action>> thenActions{};
211 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
212 EXPECT_CALL(*thenAction, execute).Times(0);
213 thenActions.push_back(std::move(thenAction));
214
215 // Create vector of actions for else clause: last action returns false
216 std::vector<std::unique_ptr<Action>> elseActions{};
217 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
218 EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(false));
219 elseActions.push_back(std::move(elseAction));
220
221 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
222 std::move(elseActions)};
223 EXPECT_EQ(ifAction.execute(env), false);
224 }
225 catch (const std::exception& error)
226 {
227 ADD_FAILURE() << "Should not have caught exception.";
228 }
229
230 // Test where condition is false: no else clause specified
231 try
232 {
233 // Create condition action that will return false
234 std::unique_ptr<MockAction> conditionAction =
235 std::make_unique<MockAction>();
236 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
237
238 // Create vector of actions for then clause: should not be executed
239 std::vector<std::unique_ptr<Action>> thenActions{};
240 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
241 EXPECT_CALL(*thenAction, execute).Times(0);
242 thenActions.push_back(std::move(thenAction));
243
244 IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
245 EXPECT_EQ(ifAction.execute(env), false);
246 }
247 catch (const std::exception& error)
248 {
249 ADD_FAILURE() << "Should not have caught exception.";
250 }
251 }
252
TEST(IfActionTests,GetConditionAction)253 TEST(IfActionTests, GetConditionAction)
254 {
255 MockAction* conditionAction = new MockAction{};
256
257 std::vector<std::unique_ptr<Action>> thenActions{};
258
259 IfAction ifAction{std::unique_ptr<Action>{conditionAction},
260 std::move(thenActions)};
261
262 EXPECT_EQ(ifAction.getConditionAction().get(), conditionAction);
263 }
264
TEST(IfActionTests,GetThenActions)265 TEST(IfActionTests, GetThenActions)
266 {
267 std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>();
268
269 std::vector<std::unique_ptr<Action>> thenActions{};
270
271 MockAction* thenAction1 = new MockAction{};
272 thenActions.push_back(std::unique_ptr<MockAction>{thenAction1});
273
274 MockAction* thenAction2 = new MockAction{};
275 thenActions.push_back(std::unique_ptr<MockAction>{thenAction2});
276
277 IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
278 EXPECT_EQ(ifAction.getThenActions().size(), 2);
279 EXPECT_EQ(ifAction.getThenActions()[0].get(), thenAction1);
280 EXPECT_EQ(ifAction.getThenActions()[1].get(), thenAction2);
281 }
282
TEST(IfActionTests,GetElseActions)283 TEST(IfActionTests, GetElseActions)
284 {
285 std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>();
286
287 std::vector<std::unique_ptr<Action>> thenActions{};
288
289 std::vector<std::unique_ptr<Action>> elseActions{};
290
291 MockAction* elseAction1 = new MockAction{};
292 elseActions.push_back(std::unique_ptr<MockAction>{elseAction1});
293
294 MockAction* elseAction2 = new MockAction{};
295 elseActions.push_back(std::unique_ptr<MockAction>{elseAction2});
296
297 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
298 std::move(elseActions)};
299 EXPECT_EQ(ifAction.getElseActions().size(), 2);
300 EXPECT_EQ(ifAction.getElseActions()[0].get(), elseAction1);
301 EXPECT_EQ(ifAction.getElseActions()[1].get(), elseAction2);
302 }
303
TEST(IfActionTests,ToString)304 TEST(IfActionTests, ToString)
305 {
306 // Test where else clause is not specified
307 {
308 std::unique_ptr<Action> conditionAction =
309 std::make_unique<MockAction>();
310
311 std::vector<std::unique_ptr<Action>> thenActions{};
312 thenActions.push_back(std::make_unique<MockAction>());
313
314 IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
315 EXPECT_EQ(ifAction.toString(),
316 "if: { condition: { ... }, then: [ ... ] }");
317 }
318
319 // Test where else clause is specified
320 {
321 std::unique_ptr<Action> conditionAction =
322 std::make_unique<MockAction>();
323
324 std::vector<std::unique_ptr<Action>> thenActions{};
325 thenActions.push_back(std::make_unique<MockAction>());
326
327 std::vector<std::unique_ptr<Action>> elseActions{};
328 elseActions.push_back(std::make_unique<MockAction>());
329
330 IfAction ifAction{std::move(conditionAction), std::move(thenActions),
331 std::move(elseActions)};
332 EXPECT_EQ(ifAction.toString(),
333 "if: { condition: { ... }, then: [ ... ], else: [ ... ] }");
334 }
335 }
336