1*6d597737SShawn McCarney /**
2*6d597737SShawn McCarney  * Copyright © 2019 IBM Corporation
3*6d597737SShawn McCarney  *
4*6d597737SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5*6d597737SShawn McCarney  * you may not use this file except in compliance with the License.
6*6d597737SShawn McCarney  * You may obtain a copy of the License at
7*6d597737SShawn McCarney  *
8*6d597737SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9*6d597737SShawn McCarney  *
10*6d597737SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11*6d597737SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12*6d597737SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6d597737SShawn McCarney  * See the License for the specific language governing permissions and
14*6d597737SShawn McCarney  * limitations under the License.
15*6d597737SShawn McCarney  */
16*6d597737SShawn McCarney #include "action.hpp"
17*6d597737SShawn McCarney #include "action_environment.hpp"
18*6d597737SShawn McCarney #include "id_map.hpp"
19*6d597737SShawn McCarney #include "if_action.hpp"
20*6d597737SShawn McCarney #include "mock_action.hpp"
21*6d597737SShawn McCarney 
22*6d597737SShawn McCarney #include <exception>
23*6d597737SShawn McCarney #include <memory>
24*6d597737SShawn McCarney #include <stdexcept>
25*6d597737SShawn McCarney #include <utility>
26*6d597737SShawn McCarney #include <vector>
27*6d597737SShawn McCarney 
28*6d597737SShawn McCarney #include <gmock/gmock.h>
29*6d597737SShawn McCarney #include <gtest/gtest.h>
30*6d597737SShawn McCarney 
31*6d597737SShawn McCarney using namespace phosphor::power::regulators;
32*6d597737SShawn McCarney 
33*6d597737SShawn McCarney using ::testing::Return;
34*6d597737SShawn McCarney using ::testing::Throw;
35*6d597737SShawn McCarney 
36*6d597737SShawn McCarney TEST(IfActionTests, Constructor)
37*6d597737SShawn McCarney {
38*6d597737SShawn McCarney     // Test where else clause is not specified
39*6d597737SShawn McCarney     {
40*6d597737SShawn McCarney         std::unique_ptr<Action> conditionAction =
41*6d597737SShawn McCarney             std::make_unique<MockAction>();
42*6d597737SShawn McCarney 
43*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
44*6d597737SShawn McCarney         thenActions.push_back(std::make_unique<MockAction>());
45*6d597737SShawn McCarney         thenActions.push_back(std::make_unique<MockAction>());
46*6d597737SShawn McCarney 
47*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
48*6d597737SShawn McCarney         EXPECT_NE(ifAction.getConditionAction().get(), nullptr);
49*6d597737SShawn McCarney         EXPECT_EQ(ifAction.getThenActions().size(), 2);
50*6d597737SShawn McCarney         EXPECT_EQ(ifAction.getElseActions().size(), 0);
51*6d597737SShawn McCarney     }
52*6d597737SShawn McCarney 
53*6d597737SShawn McCarney     // Test where else clause is specified
54*6d597737SShawn McCarney     {
55*6d597737SShawn McCarney         std::unique_ptr<Action> conditionAction =
56*6d597737SShawn McCarney             std::make_unique<MockAction>();
57*6d597737SShawn McCarney 
58*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
59*6d597737SShawn McCarney         thenActions.push_back(std::make_unique<MockAction>());
60*6d597737SShawn McCarney         thenActions.push_back(std::make_unique<MockAction>());
61*6d597737SShawn McCarney 
62*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> elseActions{};
63*6d597737SShawn McCarney         elseActions.push_back(std::make_unique<MockAction>());
64*6d597737SShawn McCarney 
65*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions),
66*6d597737SShawn McCarney                           std::move(elseActions)};
67*6d597737SShawn McCarney         EXPECT_NE(ifAction.getConditionAction().get(), nullptr);
68*6d597737SShawn McCarney         EXPECT_EQ(ifAction.getThenActions().size(), 2);
69*6d597737SShawn McCarney         EXPECT_EQ(ifAction.getElseActions().size(), 1);
70*6d597737SShawn McCarney     }
71*6d597737SShawn McCarney }
72*6d597737SShawn McCarney 
73*6d597737SShawn McCarney TEST(IfActionTests, Execute)
74*6d597737SShawn McCarney {
75*6d597737SShawn McCarney     // Create ActionEnvironment
76*6d597737SShawn McCarney     IDMap idMap{};
77*6d597737SShawn McCarney     ActionEnvironment env{idMap, ""};
78*6d597737SShawn McCarney 
79*6d597737SShawn McCarney     // Test where action throws an exception
80*6d597737SShawn McCarney     try
81*6d597737SShawn McCarney     {
82*6d597737SShawn McCarney         // Create condition action that will return true
83*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
84*6d597737SShawn McCarney             std::make_unique<MockAction>();
85*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
86*6d597737SShawn McCarney 
87*6d597737SShawn McCarney         // Create vector of actions for then clause
88*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
89*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction;
90*6d597737SShawn McCarney 
91*6d597737SShawn McCarney         // First then action will throw an exception
92*6d597737SShawn McCarney         thenAction = std::make_unique<MockAction>();
93*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute)
94*6d597737SShawn McCarney             .Times(1)
95*6d597737SShawn McCarney             .WillOnce(Throw(std::logic_error{"Communication error"}));
96*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
97*6d597737SShawn McCarney 
98*6d597737SShawn McCarney         // Second then action should not get executed
99*6d597737SShawn McCarney         thenAction = std::make_unique<MockAction>();
100*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(0);
101*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
102*6d597737SShawn McCarney 
103*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
104*6d597737SShawn McCarney         ifAction.execute(env);
105*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
106*6d597737SShawn McCarney     }
107*6d597737SShawn McCarney     catch (const std::exception& error)
108*6d597737SShawn McCarney     {
109*6d597737SShawn McCarney         EXPECT_STREQ(error.what(), "Communication error");
110*6d597737SShawn McCarney     }
111*6d597737SShawn McCarney 
112*6d597737SShawn McCarney     // Test where condition is true: then clause returns true
113*6d597737SShawn McCarney     try
114*6d597737SShawn McCarney     {
115*6d597737SShawn McCarney         // Create condition action that will return true
116*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
117*6d597737SShawn McCarney             std::make_unique<MockAction>();
118*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
119*6d597737SShawn McCarney 
120*6d597737SShawn McCarney         // Create vector of actions for then clause: last action returns true
121*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
122*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
123*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(true));
124*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
125*6d597737SShawn McCarney 
126*6d597737SShawn McCarney         // Create vector of actions for else clause: should not be executed
127*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> elseActions{};
128*6d597737SShawn McCarney         std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
129*6d597737SShawn McCarney         EXPECT_CALL(*elseAction, execute).Times(0);
130*6d597737SShawn McCarney         elseActions.push_back(std::move(elseAction));
131*6d597737SShawn McCarney 
132*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions),
133*6d597737SShawn McCarney                           std::move(elseActions)};
134*6d597737SShawn McCarney         EXPECT_EQ(ifAction.execute(env), true);
135*6d597737SShawn McCarney     }
136*6d597737SShawn McCarney     catch (const std::exception& error)
137*6d597737SShawn McCarney     {
138*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
139*6d597737SShawn McCarney     }
140*6d597737SShawn McCarney 
141*6d597737SShawn McCarney     // Test where condition is true: then clause returns false
142*6d597737SShawn McCarney     try
143*6d597737SShawn McCarney     {
144*6d597737SShawn McCarney         // Create condition action that will return true
145*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
146*6d597737SShawn McCarney             std::make_unique<MockAction>();
147*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true));
148*6d597737SShawn McCarney 
149*6d597737SShawn McCarney         // Create vector of actions for then clause: last action returns false
150*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
151*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
152*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(false));
153*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
154*6d597737SShawn McCarney 
155*6d597737SShawn McCarney         // Create vector of actions for else clause: should not be executed
156*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> elseActions{};
157*6d597737SShawn McCarney         std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
158*6d597737SShawn McCarney         EXPECT_CALL(*elseAction, execute).Times(0);
159*6d597737SShawn McCarney         elseActions.push_back(std::move(elseAction));
160*6d597737SShawn McCarney 
161*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions),
162*6d597737SShawn McCarney                           std::move(elseActions)};
163*6d597737SShawn McCarney         EXPECT_EQ(ifAction.execute(env), false);
164*6d597737SShawn McCarney     }
165*6d597737SShawn McCarney     catch (const std::exception& error)
166*6d597737SShawn McCarney     {
167*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
168*6d597737SShawn McCarney     }
169*6d597737SShawn McCarney 
170*6d597737SShawn McCarney     // Test where condition is false: else clause returns true
171*6d597737SShawn McCarney     try
172*6d597737SShawn McCarney     {
173*6d597737SShawn McCarney         // Create condition action that will return false
174*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
175*6d597737SShawn McCarney             std::make_unique<MockAction>();
176*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
177*6d597737SShawn McCarney 
178*6d597737SShawn McCarney         // Create vector of actions for then clause: should not be executed
179*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
180*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
181*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(0);
182*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
183*6d597737SShawn McCarney 
184*6d597737SShawn McCarney         // Create vector of actions for else clause: last action returns true
185*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> elseActions{};
186*6d597737SShawn McCarney         std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
187*6d597737SShawn McCarney         EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(true));
188*6d597737SShawn McCarney         elseActions.push_back(std::move(elseAction));
189*6d597737SShawn McCarney 
190*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions),
191*6d597737SShawn McCarney                           std::move(elseActions)};
192*6d597737SShawn McCarney         EXPECT_EQ(ifAction.execute(env), true);
193*6d597737SShawn McCarney     }
194*6d597737SShawn McCarney     catch (const std::exception& error)
195*6d597737SShawn McCarney     {
196*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
197*6d597737SShawn McCarney     }
198*6d597737SShawn McCarney 
199*6d597737SShawn McCarney     // Test where condition is false: else clause returns false
200*6d597737SShawn McCarney     try
201*6d597737SShawn McCarney     {
202*6d597737SShawn McCarney         // Create condition action that will return false
203*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
204*6d597737SShawn McCarney             std::make_unique<MockAction>();
205*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
206*6d597737SShawn McCarney 
207*6d597737SShawn McCarney         // Create vector of actions for then clause: should not be executed
208*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
209*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
210*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(0);
211*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
212*6d597737SShawn McCarney 
213*6d597737SShawn McCarney         // Create vector of actions for else clause: last action returns false
214*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> elseActions{};
215*6d597737SShawn McCarney         std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>();
216*6d597737SShawn McCarney         EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(false));
217*6d597737SShawn McCarney         elseActions.push_back(std::move(elseAction));
218*6d597737SShawn McCarney 
219*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions),
220*6d597737SShawn McCarney                           std::move(elseActions)};
221*6d597737SShawn McCarney         EXPECT_EQ(ifAction.execute(env), false);
222*6d597737SShawn McCarney     }
223*6d597737SShawn McCarney     catch (const std::exception& error)
224*6d597737SShawn McCarney     {
225*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
226*6d597737SShawn McCarney     }
227*6d597737SShawn McCarney 
228*6d597737SShawn McCarney     // Test where condition is false: no else clause specified
229*6d597737SShawn McCarney     try
230*6d597737SShawn McCarney     {
231*6d597737SShawn McCarney         // Create condition action that will return false
232*6d597737SShawn McCarney         std::unique_ptr<MockAction> conditionAction =
233*6d597737SShawn McCarney             std::make_unique<MockAction>();
234*6d597737SShawn McCarney         EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false));
235*6d597737SShawn McCarney 
236*6d597737SShawn McCarney         // Create vector of actions for then clause: should not be executed
237*6d597737SShawn McCarney         std::vector<std::unique_ptr<Action>> thenActions{};
238*6d597737SShawn McCarney         std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>();
239*6d597737SShawn McCarney         EXPECT_CALL(*thenAction, execute).Times(0);
240*6d597737SShawn McCarney         thenActions.push_back(std::move(thenAction));
241*6d597737SShawn McCarney 
242*6d597737SShawn McCarney         IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
243*6d597737SShawn McCarney         EXPECT_EQ(ifAction.execute(env), false);
244*6d597737SShawn McCarney     }
245*6d597737SShawn McCarney     catch (const std::exception& error)
246*6d597737SShawn McCarney     {
247*6d597737SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
248*6d597737SShawn McCarney     }
249*6d597737SShawn McCarney }
250*6d597737SShawn McCarney 
251*6d597737SShawn McCarney TEST(IfActionTests, GetConditionAction)
252*6d597737SShawn McCarney {
253*6d597737SShawn McCarney     MockAction* conditionAction = new MockAction{};
254*6d597737SShawn McCarney 
255*6d597737SShawn McCarney     std::vector<std::unique_ptr<Action>> thenActions{};
256*6d597737SShawn McCarney 
257*6d597737SShawn McCarney     IfAction ifAction{std::unique_ptr<Action>{conditionAction},
258*6d597737SShawn McCarney                       std::move(thenActions)};
259*6d597737SShawn McCarney 
260*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getConditionAction().get(), conditionAction);
261*6d597737SShawn McCarney }
262*6d597737SShawn McCarney 
263*6d597737SShawn McCarney TEST(IfActionTests, GetThenActions)
264*6d597737SShawn McCarney {
265*6d597737SShawn McCarney     std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>();
266*6d597737SShawn McCarney 
267*6d597737SShawn McCarney     std::vector<std::unique_ptr<Action>> thenActions{};
268*6d597737SShawn McCarney 
269*6d597737SShawn McCarney     MockAction* thenAction1 = new MockAction{};
270*6d597737SShawn McCarney     thenActions.push_back(std::unique_ptr<MockAction>{thenAction1});
271*6d597737SShawn McCarney 
272*6d597737SShawn McCarney     MockAction* thenAction2 = new MockAction{};
273*6d597737SShawn McCarney     thenActions.push_back(std::unique_ptr<MockAction>{thenAction2});
274*6d597737SShawn McCarney 
275*6d597737SShawn McCarney     IfAction ifAction{std::move(conditionAction), std::move(thenActions)};
276*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getThenActions().size(), 2);
277*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getThenActions()[0].get(), thenAction1);
278*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getThenActions()[1].get(), thenAction2);
279*6d597737SShawn McCarney }
280*6d597737SShawn McCarney 
281*6d597737SShawn McCarney TEST(IfActionTests, GetElseActions)
282*6d597737SShawn McCarney {
283*6d597737SShawn McCarney     std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>();
284*6d597737SShawn McCarney 
285*6d597737SShawn McCarney     std::vector<std::unique_ptr<Action>> thenActions{};
286*6d597737SShawn McCarney 
287*6d597737SShawn McCarney     std::vector<std::unique_ptr<Action>> elseActions{};
288*6d597737SShawn McCarney 
289*6d597737SShawn McCarney     MockAction* elseAction1 = new MockAction{};
290*6d597737SShawn McCarney     elseActions.push_back(std::unique_ptr<MockAction>{elseAction1});
291*6d597737SShawn McCarney 
292*6d597737SShawn McCarney     MockAction* elseAction2 = new MockAction{};
293*6d597737SShawn McCarney     elseActions.push_back(std::unique_ptr<MockAction>{elseAction2});
294*6d597737SShawn McCarney 
295*6d597737SShawn McCarney     IfAction ifAction{std::move(conditionAction), std::move(thenActions),
296*6d597737SShawn McCarney                       std::move(elseActions)};
297*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getElseActions().size(), 2);
298*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getElseActions()[0].get(), elseAction1);
299*6d597737SShawn McCarney     EXPECT_EQ(ifAction.getElseActions()[1].get(), elseAction2);
300*6d597737SShawn McCarney }
301