1*6d597737SShawn McCarney /** 2*6d597737SShawn McCarney * Copyright © 2019 IBM Corporation 3*6d597737SShawn McCarney * 4*6d597737SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 5*6d597737SShawn McCarney * you may not use this file except in compliance with the License. 6*6d597737SShawn McCarney * You may obtain a copy of the License at 7*6d597737SShawn McCarney * 8*6d597737SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 9*6d597737SShawn McCarney * 10*6d597737SShawn McCarney * Unless required by applicable law or agreed to in writing, software 11*6d597737SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 12*6d597737SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6d597737SShawn McCarney * See the License for the specific language governing permissions and 14*6d597737SShawn McCarney * limitations under the License. 15*6d597737SShawn McCarney */ 16*6d597737SShawn McCarney #include "action.hpp" 17*6d597737SShawn McCarney #include "action_environment.hpp" 18*6d597737SShawn McCarney #include "id_map.hpp" 19*6d597737SShawn McCarney #include "if_action.hpp" 20*6d597737SShawn McCarney #include "mock_action.hpp" 21*6d597737SShawn McCarney 22*6d597737SShawn McCarney #include <exception> 23*6d597737SShawn McCarney #include <memory> 24*6d597737SShawn McCarney #include <stdexcept> 25*6d597737SShawn McCarney #include <utility> 26*6d597737SShawn McCarney #include <vector> 27*6d597737SShawn McCarney 28*6d597737SShawn McCarney #include <gmock/gmock.h> 29*6d597737SShawn McCarney #include <gtest/gtest.h> 30*6d597737SShawn McCarney 31*6d597737SShawn McCarney using namespace phosphor::power::regulators; 32*6d597737SShawn McCarney 33*6d597737SShawn McCarney using ::testing::Return; 34*6d597737SShawn McCarney using ::testing::Throw; 35*6d597737SShawn McCarney 36*6d597737SShawn McCarney TEST(IfActionTests, Constructor) 37*6d597737SShawn McCarney { 38*6d597737SShawn McCarney // Test where else clause is not specified 39*6d597737SShawn McCarney { 40*6d597737SShawn McCarney std::unique_ptr<Action> conditionAction = 41*6d597737SShawn McCarney std::make_unique<MockAction>(); 42*6d597737SShawn McCarney 43*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 44*6d597737SShawn McCarney thenActions.push_back(std::make_unique<MockAction>()); 45*6d597737SShawn McCarney thenActions.push_back(std::make_unique<MockAction>()); 46*6d597737SShawn McCarney 47*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 48*6d597737SShawn McCarney EXPECT_NE(ifAction.getConditionAction().get(), nullptr); 49*6d597737SShawn McCarney EXPECT_EQ(ifAction.getThenActions().size(), 2); 50*6d597737SShawn McCarney EXPECT_EQ(ifAction.getElseActions().size(), 0); 51*6d597737SShawn McCarney } 52*6d597737SShawn McCarney 53*6d597737SShawn McCarney // Test where else clause is specified 54*6d597737SShawn McCarney { 55*6d597737SShawn McCarney std::unique_ptr<Action> conditionAction = 56*6d597737SShawn McCarney std::make_unique<MockAction>(); 57*6d597737SShawn McCarney 58*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 59*6d597737SShawn McCarney thenActions.push_back(std::make_unique<MockAction>()); 60*6d597737SShawn McCarney thenActions.push_back(std::make_unique<MockAction>()); 61*6d597737SShawn McCarney 62*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 63*6d597737SShawn McCarney elseActions.push_back(std::make_unique<MockAction>()); 64*6d597737SShawn McCarney 65*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 66*6d597737SShawn McCarney std::move(elseActions)}; 67*6d597737SShawn McCarney EXPECT_NE(ifAction.getConditionAction().get(), nullptr); 68*6d597737SShawn McCarney EXPECT_EQ(ifAction.getThenActions().size(), 2); 69*6d597737SShawn McCarney EXPECT_EQ(ifAction.getElseActions().size(), 1); 70*6d597737SShawn McCarney } 71*6d597737SShawn McCarney } 72*6d597737SShawn McCarney 73*6d597737SShawn McCarney TEST(IfActionTests, Execute) 74*6d597737SShawn McCarney { 75*6d597737SShawn McCarney // Create ActionEnvironment 76*6d597737SShawn McCarney IDMap idMap{}; 77*6d597737SShawn McCarney ActionEnvironment env{idMap, ""}; 78*6d597737SShawn McCarney 79*6d597737SShawn McCarney // Test where action throws an exception 80*6d597737SShawn McCarney try 81*6d597737SShawn McCarney { 82*6d597737SShawn McCarney // Create condition action that will return true 83*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 84*6d597737SShawn McCarney std::make_unique<MockAction>(); 85*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 86*6d597737SShawn McCarney 87*6d597737SShawn McCarney // Create vector of actions for then clause 88*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 89*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction; 90*6d597737SShawn McCarney 91*6d597737SShawn McCarney // First then action will throw an exception 92*6d597737SShawn McCarney thenAction = std::make_unique<MockAction>(); 93*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute) 94*6d597737SShawn McCarney .Times(1) 95*6d597737SShawn McCarney .WillOnce(Throw(std::logic_error{"Communication error"})); 96*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 97*6d597737SShawn McCarney 98*6d597737SShawn McCarney // Second then action should not get executed 99*6d597737SShawn McCarney thenAction = std::make_unique<MockAction>(); 100*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(0); 101*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 102*6d597737SShawn McCarney 103*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 104*6d597737SShawn McCarney ifAction.execute(env); 105*6d597737SShawn McCarney ADD_FAILURE() << "Should not have reached this line."; 106*6d597737SShawn McCarney } 107*6d597737SShawn McCarney catch (const std::exception& error) 108*6d597737SShawn McCarney { 109*6d597737SShawn McCarney EXPECT_STREQ(error.what(), "Communication error"); 110*6d597737SShawn McCarney } 111*6d597737SShawn McCarney 112*6d597737SShawn McCarney // Test where condition is true: then clause returns true 113*6d597737SShawn McCarney try 114*6d597737SShawn McCarney { 115*6d597737SShawn McCarney // Create condition action that will return true 116*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 117*6d597737SShawn McCarney std::make_unique<MockAction>(); 118*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 119*6d597737SShawn McCarney 120*6d597737SShawn McCarney // Create vector of actions for then clause: last action returns true 121*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 122*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 123*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(true)); 124*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 125*6d597737SShawn McCarney 126*6d597737SShawn McCarney // Create vector of actions for else clause: should not be executed 127*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 128*6d597737SShawn McCarney std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 129*6d597737SShawn McCarney EXPECT_CALL(*elseAction, execute).Times(0); 130*6d597737SShawn McCarney elseActions.push_back(std::move(elseAction)); 131*6d597737SShawn McCarney 132*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 133*6d597737SShawn McCarney std::move(elseActions)}; 134*6d597737SShawn McCarney EXPECT_EQ(ifAction.execute(env), true); 135*6d597737SShawn McCarney } 136*6d597737SShawn McCarney catch (const std::exception& error) 137*6d597737SShawn McCarney { 138*6d597737SShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 139*6d597737SShawn McCarney } 140*6d597737SShawn McCarney 141*6d597737SShawn McCarney // Test where condition is true: then clause returns false 142*6d597737SShawn McCarney try 143*6d597737SShawn McCarney { 144*6d597737SShawn McCarney // Create condition action that will return true 145*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 146*6d597737SShawn McCarney std::make_unique<MockAction>(); 147*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(true)); 148*6d597737SShawn McCarney 149*6d597737SShawn McCarney // Create vector of actions for then clause: last action returns false 150*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 151*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 152*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(1).WillOnce(Return(false)); 153*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 154*6d597737SShawn McCarney 155*6d597737SShawn McCarney // Create vector of actions for else clause: should not be executed 156*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 157*6d597737SShawn McCarney std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 158*6d597737SShawn McCarney EXPECT_CALL(*elseAction, execute).Times(0); 159*6d597737SShawn McCarney elseActions.push_back(std::move(elseAction)); 160*6d597737SShawn McCarney 161*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 162*6d597737SShawn McCarney std::move(elseActions)}; 163*6d597737SShawn McCarney EXPECT_EQ(ifAction.execute(env), false); 164*6d597737SShawn McCarney } 165*6d597737SShawn McCarney catch (const std::exception& error) 166*6d597737SShawn McCarney { 167*6d597737SShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 168*6d597737SShawn McCarney } 169*6d597737SShawn McCarney 170*6d597737SShawn McCarney // Test where condition is false: else clause returns true 171*6d597737SShawn McCarney try 172*6d597737SShawn McCarney { 173*6d597737SShawn McCarney // Create condition action that will return false 174*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 175*6d597737SShawn McCarney std::make_unique<MockAction>(); 176*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 177*6d597737SShawn McCarney 178*6d597737SShawn McCarney // Create vector of actions for then clause: should not be executed 179*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 180*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 181*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(0); 182*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 183*6d597737SShawn McCarney 184*6d597737SShawn McCarney // Create vector of actions for else clause: last action returns true 185*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 186*6d597737SShawn McCarney std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 187*6d597737SShawn McCarney EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(true)); 188*6d597737SShawn McCarney elseActions.push_back(std::move(elseAction)); 189*6d597737SShawn McCarney 190*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 191*6d597737SShawn McCarney std::move(elseActions)}; 192*6d597737SShawn McCarney EXPECT_EQ(ifAction.execute(env), true); 193*6d597737SShawn McCarney } 194*6d597737SShawn McCarney catch (const std::exception& error) 195*6d597737SShawn McCarney { 196*6d597737SShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 197*6d597737SShawn McCarney } 198*6d597737SShawn McCarney 199*6d597737SShawn McCarney // Test where condition is false: else clause returns false 200*6d597737SShawn McCarney try 201*6d597737SShawn McCarney { 202*6d597737SShawn McCarney // Create condition action that will return false 203*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 204*6d597737SShawn McCarney std::make_unique<MockAction>(); 205*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 206*6d597737SShawn McCarney 207*6d597737SShawn McCarney // Create vector of actions for then clause: should not be executed 208*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 209*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 210*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(0); 211*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 212*6d597737SShawn McCarney 213*6d597737SShawn McCarney // Create vector of actions for else clause: last action returns false 214*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 215*6d597737SShawn McCarney std::unique_ptr<MockAction> elseAction = std::make_unique<MockAction>(); 216*6d597737SShawn McCarney EXPECT_CALL(*elseAction, execute).Times(1).WillOnce(Return(false)); 217*6d597737SShawn McCarney elseActions.push_back(std::move(elseAction)); 218*6d597737SShawn McCarney 219*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 220*6d597737SShawn McCarney std::move(elseActions)}; 221*6d597737SShawn McCarney EXPECT_EQ(ifAction.execute(env), false); 222*6d597737SShawn McCarney } 223*6d597737SShawn McCarney catch (const std::exception& error) 224*6d597737SShawn McCarney { 225*6d597737SShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 226*6d597737SShawn McCarney } 227*6d597737SShawn McCarney 228*6d597737SShawn McCarney // Test where condition is false: no else clause specified 229*6d597737SShawn McCarney try 230*6d597737SShawn McCarney { 231*6d597737SShawn McCarney // Create condition action that will return false 232*6d597737SShawn McCarney std::unique_ptr<MockAction> conditionAction = 233*6d597737SShawn McCarney std::make_unique<MockAction>(); 234*6d597737SShawn McCarney EXPECT_CALL(*conditionAction, execute).Times(1).WillOnce(Return(false)); 235*6d597737SShawn McCarney 236*6d597737SShawn McCarney // Create vector of actions for then clause: should not be executed 237*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 238*6d597737SShawn McCarney std::unique_ptr<MockAction> thenAction = std::make_unique<MockAction>(); 239*6d597737SShawn McCarney EXPECT_CALL(*thenAction, execute).Times(0); 240*6d597737SShawn McCarney thenActions.push_back(std::move(thenAction)); 241*6d597737SShawn McCarney 242*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 243*6d597737SShawn McCarney EXPECT_EQ(ifAction.execute(env), false); 244*6d597737SShawn McCarney } 245*6d597737SShawn McCarney catch (const std::exception& error) 246*6d597737SShawn McCarney { 247*6d597737SShawn McCarney ADD_FAILURE() << "Should not have caught exception."; 248*6d597737SShawn McCarney } 249*6d597737SShawn McCarney } 250*6d597737SShawn McCarney 251*6d597737SShawn McCarney TEST(IfActionTests, GetConditionAction) 252*6d597737SShawn McCarney { 253*6d597737SShawn McCarney MockAction* conditionAction = new MockAction{}; 254*6d597737SShawn McCarney 255*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 256*6d597737SShawn McCarney 257*6d597737SShawn McCarney IfAction ifAction{std::unique_ptr<Action>{conditionAction}, 258*6d597737SShawn McCarney std::move(thenActions)}; 259*6d597737SShawn McCarney 260*6d597737SShawn McCarney EXPECT_EQ(ifAction.getConditionAction().get(), conditionAction); 261*6d597737SShawn McCarney } 262*6d597737SShawn McCarney 263*6d597737SShawn McCarney TEST(IfActionTests, GetThenActions) 264*6d597737SShawn McCarney { 265*6d597737SShawn McCarney std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>(); 266*6d597737SShawn McCarney 267*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 268*6d597737SShawn McCarney 269*6d597737SShawn McCarney MockAction* thenAction1 = new MockAction{}; 270*6d597737SShawn McCarney thenActions.push_back(std::unique_ptr<MockAction>{thenAction1}); 271*6d597737SShawn McCarney 272*6d597737SShawn McCarney MockAction* thenAction2 = new MockAction{}; 273*6d597737SShawn McCarney thenActions.push_back(std::unique_ptr<MockAction>{thenAction2}); 274*6d597737SShawn McCarney 275*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions)}; 276*6d597737SShawn McCarney EXPECT_EQ(ifAction.getThenActions().size(), 2); 277*6d597737SShawn McCarney EXPECT_EQ(ifAction.getThenActions()[0].get(), thenAction1); 278*6d597737SShawn McCarney EXPECT_EQ(ifAction.getThenActions()[1].get(), thenAction2); 279*6d597737SShawn McCarney } 280*6d597737SShawn McCarney 281*6d597737SShawn McCarney TEST(IfActionTests, GetElseActions) 282*6d597737SShawn McCarney { 283*6d597737SShawn McCarney std::unique_ptr<Action> conditionAction = std::make_unique<MockAction>(); 284*6d597737SShawn McCarney 285*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> thenActions{}; 286*6d597737SShawn McCarney 287*6d597737SShawn McCarney std::vector<std::unique_ptr<Action>> elseActions{}; 288*6d597737SShawn McCarney 289*6d597737SShawn McCarney MockAction* elseAction1 = new MockAction{}; 290*6d597737SShawn McCarney elseActions.push_back(std::unique_ptr<MockAction>{elseAction1}); 291*6d597737SShawn McCarney 292*6d597737SShawn McCarney MockAction* elseAction2 = new MockAction{}; 293*6d597737SShawn McCarney elseActions.push_back(std::unique_ptr<MockAction>{elseAction2}); 294*6d597737SShawn McCarney 295*6d597737SShawn McCarney IfAction ifAction{std::move(conditionAction), std::move(thenActions), 296*6d597737SShawn McCarney std::move(elseActions)}; 297*6d597737SShawn McCarney EXPECT_EQ(ifAction.getElseActions().size(), 2); 298*6d597737SShawn McCarney EXPECT_EQ(ifAction.getElseActions()[0].get(), elseAction1); 299*6d597737SShawn McCarney EXPECT_EQ(ifAction.getElseActions()[1].get(), elseAction2); 300*6d597737SShawn McCarney } 301