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