package com.griddynamics.jagger.invoker.scenario; import com.griddynamics.jagger.invoker.InvocationException; import com.griddynamics.jagger.invoker.Invoker; import com.griddynamics.jagger.invoker.v2.JHttpResponse; import com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.stream.Collectors; import static com.google.common.collect.Lists.newArrayList; /** * This invoker is able to execute user scenarios ({@link JHttpUserScenario}) * * @ingroup Main_Http_User_Scenario_group */ public class JHttpUserScenarioInvoker implements Invoker<Void, JHttpUserScenarioInvocationResult, JHttpUserScenario> { private final SpringBasedHttpClient httpClient = new SpringBasedHttpClient(); private static Logger log = LoggerFactory.getLogger(JHttpUserScenarioInvoker.class); @Override public JHttpUserScenarioInvocationResult invoke(Void nothing, JHttpUserScenario scenario) throws InvocationException { Boolean scenarioSucceeded = true; JHttpUserScenarioStep previousStep = null; List<JHttpUserScenarioStepInvocationResult> stepInvocationResults = new ArrayList<>(); JHttpScenarioGlobalContext localScenarioContext = scenario.getScenarioGlobalContext().copy(); for (JHttpUserScenarioStep userScenarioStep : scenario.getUserScenarioSteps()) { // Pre process step: internal setup. Can be later overridden by the user // Basic auth if (localScenarioContext.getPassword() != null && localScenarioContext.getUserName() != null) { String value = Base64.getEncoder().encodeToString((localScenarioContext.getUserName() + ":" + localScenarioContext.getPassword()).getBytes()); userScenarioStep.getQuery().header("Authorization", "Basic " + value); } // Pre process step: user actions executed before request userScenarioStep.preProcessGlobalContext(previousStep, localScenarioContext); userScenarioStep.preProcess(previousStep); // check endpoint for null if (localScenarioContext.getGlobalEndpoint() == null && userScenarioStep.getEndpoint() == null) throw new IllegalArgumentException("Endpoint must not be null! Please, set global endpoint or set endpoint for every step."); // use global endpoint for step if step has none if (userScenarioStep.getEndpoint() == null) userScenarioStep.setEndpoint(localScenarioContext.getGlobalEndpoint()); // copy global headers and cookies to current step if query is present if (localScenarioContext.getGlobalHeaders() != null && userScenarioStep.getQuery() != null) { localScenarioContext.getGlobalHeaders().forEach((header, values) -> { if (userScenarioStep.getQuery().getHeaders() != null && userScenarioStep.getQuery().getHeaders().containsKey(header)) { List<String> newValues = newArrayList(userScenarioStep.getQuery().getHeaders().get(header)); newValues.addAll(values); userScenarioStep.getQuery().getHeaders().put(header, newValues.stream().distinct().collect( Collectors.toList())); } else { userScenarioStep.getQuery().header(header, values); } }); } log.info("Step {}: {}", userScenarioStep.getStepNumber(), userScenarioStep.getStepId()); log.info("Endpoint: {}", userScenarioStep.getEndpoint()); log.info("Query: {}", userScenarioStep.getQuery()); // Request execution step long requestStartTime = System.nanoTime(); JHttpResponse response = httpClient.execute(userScenarioStep.getEndpoint(), userScenarioStep.getQuery()); Double requestTimeInMilliseconds = (System.nanoTime() - requestStartTime) / 1_000_000.0; //TODO: JFG-1121 log.info("Response: {}", response); // Wait after execution if needed userScenarioStep.waitAfterExecution(); // Post process step: executed after request. If returned false, scenario invocation stops. Boolean succeeded = userScenarioStep.postProcess(response); stepInvocationResults.add(new JHttpUserScenarioStepInvocationResult(userScenarioStep.getStepId(), userScenarioStep.getStepDisplayName(), requestTimeInMilliseconds, succeeded)); previousStep = userScenarioStep; if (!succeeded) { scenarioSucceeded = false; log.error("Step {} '{}' post process returned false! Stopping scenario (next steps won't be executed).", userScenarioStep.getStepId(), userScenarioStep.getStepDisplayName()); break; } } return new JHttpUserScenarioInvocationResult(stepInvocationResults, scenario.getScenarioId(), scenario.getScenarioDisplayName(), scenarioSucceeded); } }