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