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 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(IfActionTests, Constructor) 37 { 38 // Test where else clause is not specified 39 { 40 std::unique_ptr<Action> conditionAction = 41 std::make_unique<MockAction>(); 42 43 std::vector<std::unique_ptr<Action>> thenActions{}; 44 thenActions.push_back(std::make_unique<MockAction>()); 45 thenActions.push_back(std::make_unique<MockAction>()); 46 47 IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 48 EXPECT_NE(ifAction.getConditionAction().get(), nullptr); 49 EXPECT_EQ(ifAction.getThenActions().size(), 2); 50 EXPECT_EQ(ifAction.getElseActions().size(), 0); 51 } 52 53 // Test where else clause is specified 54 { 55 std::unique_ptr<Action> conditionAction = 56 std::make_unique<MockAction>(); 57 58 std::vector<std::unique_ptr<Action>> thenActions{}; 59 thenActions.push_back(std::make_unique<MockAction>()); 60 thenActions.push_back(std::make_unique<MockAction>()); 61 62 std::vector<std::unique_ptr<Action>> elseActions{}; 63 elseActions.push_back(std::make_unique<MockAction>()); 64 65 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 66 std::move(elseActions)}; 67 EXPECT_NE(ifAction.getConditionAction().get(), nullptr); 68 EXPECT_EQ(ifAction.getThenActions().size(), 2); 69 EXPECT_EQ(ifAction.getElseActions().size(), 1); 70 } 71 } 72 73 TEST(IfActionTests, Execute) 74 { 75 // Create ActionEnvironment 76 IDMap idMap{}; 77 ActionEnvironment env{idMap, ""}; 78 79 // Test where action throws an exception 80 try 81 { 82 // Create condition action that will return true 83 std::unique_ptr<MockAction> conditionAction = 84 std::make_unique<MockAction>(); 85 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 86 87 // Create vector of actions for then clause 88 std::vector<std::unique_ptr<Action>> thenActions{}; 89 std::unique_ptr<MockAction> thenAction; 90 91 // First then action will throw an exception 92 thenAction = std::make_unique<MockAction>(); 93 EXPECT_CALL(*thenAction, execute) 94 .Times(1) 95 .WillOnce(Throw(std::logic_error{"Communication error"})); 96 thenActions.push_back(std::move(thenAction)); 97 98 // Second then action should not get executed 99 thenAction = std::make_unique<MockAction>(); 100 EXPECT_CALL(*thenAction, execute).Times(0); 101 thenActions.push_back(std::move(thenAction)); 102 103 IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 104 ifAction.execute(env); 105 ADD_FAILURE() << "Should not have reached this line."; 106 } 107 catch (const std::exception& error) 108 { 109 EXPECT_STREQ(error.what(), "Communication error"); 110 } 111 112 // Test where condition is true: then clause returns true 113 try 114 { 115 // Create condition action that will return true 116 std::unique_ptr<MockAction> conditionAction = 117 std::make_unique<MockAction>(); 118 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 119 120 // Create vector of actions for then clause: last action returns true 121 std::vector<std::unique_ptr<Action>> thenActions{}; 122 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 123 EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(true)); 124 thenActions.push_back(std::move(thenAction)); 125 126 // Create vector of actions for else clause: should not be executed 127 std::vector<std::unique_ptr<Action>> elseActions{}; 128 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 129 EXPECT_CALL(*elseAction, execute).Times(0); 130 elseActions.push_back(std::move(elseAction)); 131 132 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 133 std::move(elseActions)}; 134 EXPECT_EQ(ifAction.execute(env), true); 135 } 136 catch (const std::exception& error) 137 { 138 ADD_FAILURE() << "Should not have caught exception."; 139 } 140 141 // Test where condition is true: then clause returns false 142 try 143 { 144 // Create condition action that will return true 145 std::unique_ptr<MockAction> conditionAction = 146 std::make_unique<MockAction>(); 147 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 148 149 // Create vector of actions for then clause: last action returns false 150 std::vector<std::unique_ptr<Action>> thenActions{}; 151 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 152 EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(false)); 153 thenActions.push_back(std::move(thenAction)); 154 155 // Create vector of actions for else clause: should not be executed 156 std::vector<std::unique_ptr<Action>> elseActions{}; 157 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 158 EXPECT_CALL(*elseAction, execute).Times(0); 159 elseActions.push_back(std::move(elseAction)); 160 161 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 162 std::move(elseActions)}; 163 EXPECT_EQ(ifAction.execute(env), false); 164 } 165 catch (const std::exception& error) 166 { 167 ADD_FAILURE() << "Should not have caught exception."; 168 } 169 170 // Test where condition is false: else clause returns true 171 try 172 { 173 // Create condition action that will return false 174 std::unique_ptr<MockAction> conditionAction = 175 std::make_unique<MockAction>(); 176 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 177 178 // Create vector of actions for then clause: should not be executed 179 std::vector<std::unique_ptr<Action>> thenActions{}; 180 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 181 EXPECT_CALL(*thenAction, execute).Times(0); 182 thenActions.push_back(std::move(thenAction)); 183 184 // Create vector of actions for else clause: last action returns true 185 std::vector<std::unique_ptr<Action>> elseActions{}; 186 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 187 EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(true)); 188 elseActions.push_back(std::move(elseAction)); 189 190 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 191 std::move(elseActions)}; 192 EXPECT_EQ(ifAction.execute(env), true); 193 } 194 catch (const std::exception& error) 195 { 196 ADD_FAILURE() << "Should not have caught exception."; 197 } 198 199 // Test where condition is false: else clause returns false 200 try 201 { 202 // Create condition action that will return false 203 std::unique_ptr<MockAction> conditionAction = 204 std::make_unique<MockAction>(); 205 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 206 207 // Create vector of actions for then clause: should not be executed 208 std::vector<std::unique_ptr<Action>> thenActions{}; 209 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 210 EXPECT_CALL(*thenAction, execute).Times(0); 211 thenActions.push_back(std::move(thenAction)); 212 213 // Create vector of actions for else clause: last action returns false 214 std::vector<std::unique_ptr<Action>> elseActions{}; 215 std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 216 EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(false)); 217 elseActions.push_back(std::move(elseAction)); 218 219 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 220 std::move(elseActions)}; 221 EXPECT_EQ(ifAction.execute(env), false); 222 } 223 catch (const std::exception& error) 224 { 225 ADD_FAILURE() << "Should not have caught exception."; 226 } 227 228 // Test where condition is false: no else clause specified 229 try 230 { 231 // Create condition action that will return false 232 std::unique_ptr<MockAction> conditionAction = 233 std::make_unique<MockAction>(); 234 EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 235 236 // Create vector of actions for then clause: should not be executed 237 std::vector<std::unique_ptr<Action>> thenActions{}; 238 std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 239 EXPECT_CALL(*thenAction, execute).Times(0); 240 thenActions.push_back(std::move(thenAction)); 241 242 IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 243 EXPECT_EQ(ifAction.execute(env), false); 244 } 245 catch (const std::exception& error) 246 { 247 ADD_FAILURE() << "Should not have caught exception."; 248 } 249 } 250 251 TEST(IfActionTests, GetConditionAction) 252 { 253 MockAction* conditionAction = new MockAction{}; 254 255 std::vector<std::unique_ptr<Action>> thenActions{}; 256 257 IfAction ifAction{std::unique_ptr<Action>{conditionAction}, 258 std::move(thenActions)}; 259 260 EXPECT_EQ(ifAction.getConditionAction().get(), conditionAction); 261 } 262 263 TEST(IfActionTests, GetThenActions) 264 { 265 std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>(); 266 267 std::vector<std::unique_ptr<Action>> thenActions{}; 268 269 MockAction* thenAction1 = new MockAction{}; 270 thenActions.push_back(std::unique_ptr<MockAction>{thenAction1}); 271 272 MockAction* thenAction2 = new MockAction{}; 273 thenActions.push_back(std::unique_ptr<MockAction>{thenAction2}); 274 275 IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 276 EXPECT_EQ(ifAction.getThenActions().size(), 2); 277 EXPECT_EQ(ifAction.getThenActions()[0].get(), thenAction1); 278 EXPECT_EQ(ifAction.getThenActions()[1].get(), thenAction2); 279 } 280 281 TEST(IfActionTests, GetElseActions) 282 { 283 std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>(); 284 285 std::vector<std::unique_ptr<Action>> thenActions{}; 286 287 std::vector<std::unique_ptr<Action>> elseActions{}; 288 289 MockAction* elseAction1 = new MockAction{}; 290 elseActions.push_back(std::unique_ptr<MockAction>{elseAction1}); 291 292 MockAction* elseAction2 = new MockAction{}; 293 elseActions.push_back(std::unique_ptr<MockAction>{elseAction2}); 294 295 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 296 std::move(elseActions)}; 297 EXPECT_EQ(ifAction.getElseActions().size(), 2); 298 EXPECT_EQ(ifAction.getElseActions()[0].get(), elseAction1); 299 EXPECT_EQ(ifAction.getElseActions()[1].get(), elseAction2); 300 } 301 302 TEST(IfActionTests, ToString) 303 { 304 // Test where else clause is not specified 305 { 306 std::unique_ptr<Action> conditionAction = 307 std::make_unique<MockAction>(); 308 309 std::vector<std::unique_ptr<Action>> thenActions{}; 310 thenActions.push_back(std::make_unique<MockAction>()); 311 312 IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 313 EXPECT_EQ(ifAction.toString(), 314 "if: { condition: { ... }, then: [ ... ] }"); 315 } 316 317 // Test where else clause is specified 318 { 319 std::unique_ptr<Action> conditionAction = 320 std::make_unique<MockAction>(); 321 322 std::vector<std::unique_ptr<Action>> thenActions{}; 323 thenActions.push_back(std::make_unique<MockAction>()); 324 325 std::vector<std::unique_ptr<Action>> elseActions{}; 326 elseActions.push_back(std::make_unique<MockAction>()); 327 328 IfAction ifAction{std::move(conditionAction), std::move(thenActions), 329 std::move(elseActions)}; 330 EXPECT_EQ(ifAction.toString(), 331 "if: { condition: { ... }, then: [ ... ], else: [ ... ] }"); 332 } 333 } 334