xref: /openbmc/phosphor-power/phosphor-regulators/test/actions/if_action_tests.cpp (revision 73eaceeba59657db9a25811cb7f14d6a7df14069)
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