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 "mock_action.hpp"
20 #include "mock_services.hpp"
21 #include "or_action.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(OrActionTests,Constructor)37 TEST(OrActionTests, Constructor)
38 {
39     std::vector<std::unique_ptr<Action>> actions{};
40     actions.push_back(std::make_unique<MockAction>());
41     actions.push_back(std::make_unique<MockAction>());
42 
43     OrAction orAction{std::move(actions)};
44     EXPECT_EQ(orAction.getActions().size(), 2);
45 }
46 
TEST(OrActionTests,Execute)47 TEST(OrActionTests, Execute)
48 {
49     // Create ActionEnvironment
50     IDMap idMap{};
51     // Create MockServices.
52     MockServices services{};
53     ActionEnvironment env{idMap, "", services};
54 
55     // Test where empty vector of actions is specified
56     try
57     {
58         std::vector<std::unique_ptr<Action>> actions{};
59         OrAction orAction{std::move(actions)};
60         EXPECT_EQ(orAction.execute(env), false);
61     }
62     catch (const std::exception& error)
63     {
64         ADD_FAILURE() << "Should not have caught exception.";
65     }
66 
67     // Test where action throws an exception
68     try
69     {
70         std::vector<std::unique_ptr<Action>> actions{};
71         std::unique_ptr<MockAction> action;
72 
73         // First action will throw an exception
74         action = std::make_unique<MockAction>();
75         EXPECT_CALL(*action, execute)
76             .Times(1)
77             .WillOnce(Throw(std::logic_error{"Communication error"}));
78         actions.push_back(std::move(action));
79 
80         // Second action should not get executed
81         action = std::make_unique<MockAction>();
82         EXPECT_CALL(*action, execute).Times(0);
83         actions.push_back(std::move(action));
84 
85         OrAction orAction{std::move(actions)};
86         orAction.execute(env);
87         ADD_FAILURE() << "Should not have reached this line.";
88     }
89     catch (const std::exception& error)
90     {
91         EXPECT_STREQ(error.what(), "Communication error");
92     }
93 
94     // Test where middle action returns true
95     try
96     {
97         std::vector<std::unique_ptr<Action>> actions{};
98         std::unique_ptr<MockAction> action;
99 
100         // First action will return false
101         action = std::make_unique<MockAction>();
102         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
103         actions.push_back(std::move(action));
104 
105         // Second action will return true
106         action = std::make_unique<MockAction>();
107         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
108         actions.push_back(std::move(action));
109 
110         // Third action will return false
111         action = std::make_unique<MockAction>();
112         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
113         actions.push_back(std::move(action));
114 
115         OrAction orAction{std::move(actions)};
116         EXPECT_EQ(orAction.execute(env), true);
117     }
118     catch (const std::exception& error)
119     {
120         ADD_FAILURE() << "Should not have caught exception.";
121     }
122 
123     // Test where all actions return false
124     try
125     {
126         std::vector<std::unique_ptr<Action>> actions{};
127         std::unique_ptr<MockAction> action;
128 
129         // First action will return false
130         action = std::make_unique<MockAction>();
131         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
132         actions.push_back(std::move(action));
133 
134         // Second action will return false
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         // Third action will return false
140         action = std::make_unique<MockAction>();
141         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
142         actions.push_back(std::move(action));
143 
144         OrAction orAction{std::move(actions)};
145         EXPECT_EQ(orAction.execute(env), false);
146     }
147     catch (const std::exception& error)
148     {
149         ADD_FAILURE() << "Should not have caught exception.";
150     }
151 }
152 
TEST(OrActionTests,GetActions)153 TEST(OrActionTests, GetActions)
154 {
155     std::vector<std::unique_ptr<Action>> actions{};
156 
157     MockAction* action1 = new MockAction{};
158     actions.push_back(std::unique_ptr<MockAction>{action1});
159 
160     MockAction* action2 = new MockAction{};
161     actions.push_back(std::unique_ptr<MockAction>{action2});
162 
163     OrAction orAction{std::move(actions)};
164     EXPECT_EQ(orAction.getActions().size(), 2);
165     EXPECT_EQ(orAction.getActions()[0].get(), action1);
166     EXPECT_EQ(orAction.getActions()[1].get(), action2);
167 }
168 
TEST(OrActionTests,ToString)169 TEST(OrActionTests, ToString)
170 {
171     std::vector<std::unique_ptr<Action>> actions{};
172     actions.push_back(std::make_unique<MockAction>());
173 
174     OrAction orAction{std::move(actions)};
175     EXPECT_EQ(orAction.toString(), "or: [ ... ]");
176 }
177