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