package com.intuit.tank.common; /* * #%L * Common * %% * Copyright (C) 2011 - 2015 Intuit Inc. * %% * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * #L% */ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.intuit.tank.project.RequestData; import com.intuit.tank.project.Script; import com.intuit.tank.project.ScriptStep; import com.intuit.tank.script.ScriptConstants; import com.intuit.tank.vm.common.TankConstants; import com.intuit.tank.vm.common.util.ValidationUtil; import com.intuit.tank.vm.settings.TimeUtil; import com.intuit.tank.vm.settings.TankConfig; public class ScriptUtil { private static final Logger LOG = LogManager.getLogger(ScriptUtil.class); public static final String TOTAL_TIME_KEY = "_totalTime"; public static final String START_TIME_KEY = "_startTime"; private static final Pattern p = Pattern.compile(TankConstants.EXPRESSION_REGEX); private static final Pattern csvPattern = Pattern.compile(TankConstants.CSV_EXPRESSION_REGEX); public static long getRunTime(List<ScriptStep> steps, Map<String, String> variables) { long runTime = 0; TankConfig tankConfig = new TankConfig(); for (ScriptStep step : steps) { runTime += calculateStepDuration(step, variables, tankConfig); } return runTime; } public static Set<String> getUsedVariables(ScriptStep step) { Set<String> ret = new HashSet<String>(); ret.addAll(extractVariablesFromRequestData(step.getData())); ret.addAll(extractVariablesFromRequestData(step.getQueryStrings())); ret.addAll(extractVariablesFromRequestData(step.getPostDatas())); ret.addAll(extractVariablesFromRequestData(step.getRequestheaders())); ret.addAll(extractVariablesFromRequestData(step.getRequestCookies())); extractVariables(ret, step.getPayload()); extractVariables(ret, step.getHostname()); extractVariables(ret, step.getSimplePath()); return ret; } public static Map<String, String> getDeclaredVariables(ScriptStep step) { Map<String, String> ret = new HashMap<String, String>(); if (step.getType().equals("variable")) { addKeys(ret, step.getData(), null); } return ret; } public static List<ScriptAssignment> getAssignments(ScriptStep step) { List<ScriptAssignment> ret = new ArrayList<ScriptAssignment>(); if (step.getType().equals("request")) { for (RequestData rd : step.getResponseData()) { if (StringUtils.isNotBlank(rd.getKey())) { if (StringUtils.containsIgnoreCase(rd.getType(), "assignment")) { ret.add(new ScriptAssignment(rd.getKey().trim(), StringUtils.removeStart( StringUtils.trim(rd.getValue()), "="), step.getStepIndex())); } } } } return ret; } private static void addKeys(Map<String, String> ret, Set<RequestData> rds, String type) { for (RequestData rd : rds) { if (StringUtils.isNotBlank(rd.getKey())) { if (type == null || StringUtils.containsIgnoreCase(rd.getType(), type)) { ret.put(rd.getKey().trim(), StringUtils.trim(rd.getValue())); } } } } private static Set<String> extractVariablesFromRequestData(Set<RequestData> rds) { Set<String> ret = new HashSet<String>(); for (RequestData rd : rds) { extractVariables(ret, rd.getKey()); extractVariables(ret, rd.getValue()); } return ret; } private static void extractVariables(Set<String> ret, String s) { if (StringUtils.isNotBlank(s)) { if (ValidationUtil.isVariable(s)) { ret.add(ValidationUtil.removeVariableIdentifier(s)); } else { Matcher m = p.matcher(s); while (m.find()) { // find next match String group = m.group(1).trim(); getVar(ret, group); } } } } private static void getVar(Set<String> ret, String s) { Set<String> toTest = new HashSet<String>(); StringBuilder sb = new StringBuilder(); for (char c : s.toCharArray()) { if (c == ',' || c == ')') { toTest.add(sb.toString()); sb = new StringBuilder(); } else if (c == '(') { sb = new StringBuilder(); } else { sb.append(c); } } toTest.add(sb.toString()); for (String group : toTest) { group = group.trim(); if (StringUtils.isNotBlank(group) && StringUtils.containsNone(group, " ()'\",")) { if (!NumberUtils.isNumber(group)) { // its a variable ret.add(group); } } } } public static Script copyScript(String creator, String name, Script original) { Script ret = new Script(); ret.setComments(original.getComments()); ret.setCreator(creator); ret.setName(name); ret.setProductName(original.getProductName()); ret.setRuntime(original.getRuntime()); for (ScriptStep step : original.getScriptSteps()) { ret.addStep(step); } return ret; } /** * @param script */ public static void setScriptStepLabels(Script script) { int i = 1; boolean copy = script.getId() == 0; if (script.getScriptSteps() != null) { for (ScriptStep step : script.getScriptSteps()) { step.setStepIndex(i++); if (copy || step.getUuid() == null) { step.setUuid(UUID.randomUUID().toString()); } updateStepLabel(step); } } } public static void updateStepLabel(ScriptStep step) { step.setLabel(getStepLabel(step)); if (ScriptConstants.THINK_TIME.equals(step.getType())) { step.setComments(getThinkTimeComment(step)); } else if (ScriptConstants.SLEEP.equals(step.getType())) { step.setComments(getSleepTimeComment(step)); } } /** * @param step * @return */ private static String getThinkTimeComment(ScriptStep step) { String min = null; String max = null; for (RequestData rd : step.getData()) { if (ScriptConstants.MIN_TIME.equals(rd.getKey())) { min = rd.getValue(); } else if (ScriptConstants.MAX_TIME.equals(rd.getKey())) { max = rd.getValue(); } } return "ThinkTime " + min + "-" + max; } /** * @param step */ private static String getSleepTimeComment(ScriptStep step) { String delay = null; for (RequestData rd : step.getData()) { if (ScriptConstants.TIME.equals(rd.getKey())) { delay = rd.getValue(); } } return "SLEEP " + delay; } /** * @param step * @return */ private static String getStepLabel(ScriptStep step) { StringBuilder label = new StringBuilder(); if (step.getType().equalsIgnoreCase(ScriptConstants.REQUEST)) { label.append(step.getProtocol()).append("://").append(step.getHostname()).append(step.getSimplePath()); int qsCount = 0; if (step.getQueryStrings() != null) { for (RequestData qs : step.getQueryStrings()) { label.append(qsCount == 0 ? "?" : "&"); label.append(qs.getKey()).append("=").append(qs.getValue()); qsCount++; } } } else if (step.getType().equalsIgnoreCase(ScriptConstants.VARIABLE)) { Set<RequestData> setData = step.getData(); if (null != setData) { Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); label.append("Variable definition " + d.getKey() + "=>" + d.getValue()); } } } else if (step.getType().equalsIgnoreCase(ScriptConstants.AUTHENTICATION)) { Set<RequestData> setData = step.getData(); if (null != setData) { String scheme = "ALL"; String host = ""; String user = ""; Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); if (d.getKey().equals(ScriptConstants.AUTH_SCHEME)) { scheme = d.getValue(); } else if (d.getKey().equals(ScriptConstants.AUTH_HOST)) { host = d.getValue(); } else if (d.getKey().equals(ScriptConstants.AUTH_USER_NAME)) { user = d.getValue(); } } label.append("Authentication " + scheme + " [host: " + host + " user: " + user + "]"); } } else if (step.getType().equalsIgnoreCase(ScriptConstants.THINK_TIME)) { String min = "0"; String max = "0"; Set<RequestData> setData = step.getData(); if (null != setData) { Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); if (d.getKey().contains("min")) min = d.getValue(); else if (d.getKey().contains("max")) max = d.getValue(); } } label.append("Think time " + min + "-" + max); } else if (step.getType().equalsIgnoreCase(ScriptConstants.LOGIC)) { label.append("Logic Step: " + step.getName()); } else if (step.getType().equalsIgnoreCase(ScriptConstants.COOKIE)) { String name = ""; String value = ""; for (RequestData requestData : step.getData()) { if (ScriptConstants.COOKIE_NAME.equals(requestData.getKey())) { name = requestData.getValue(); } if (ScriptConstants.COOKIE_VALUE.equals(requestData.getKey())) { value = requestData.getValue(); } // if (ScriptConstants.COOKIE_DOMAIN.equals(requestData.getKey())) { // domain = requestData.getValue(); // } } label.append("Set Cookie: ").append(name).append(" = ").append(value).toString(); } else if (step.getType().equalsIgnoreCase(ScriptConstants.SLEEP)) { Set<RequestData> setData = step.getData(); if (null != setData) { Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); label.append("Sleep for " + d.getValue()); } } } else if (step.getType().equalsIgnoreCase(ScriptConstants.CLEAR)) { label.append("Clear session"); } else if (step.getType().equalsIgnoreCase(ScriptConstants.TIMER)) { String name = null; String timerAction = null; for (RequestData rd : step.getData()) { if (rd.getKey().equalsIgnoreCase(ScriptConstants.IS_START)) { timerAction = rd.getValue(); } if (rd.getKey().equalsIgnoreCase(ScriptConstants.LOGGING_KEY)) { name = rd.getValue(); } } label.append(name).append(":").append(timerAction); } return StringUtils.abbreviate(label.toString(), 1024); } /** * @param count * @param step * @return */ /* * public static ScriptStep requestToStep(int count, ScriptStep step) { ScriptStep step = new ScriptStep(); * * step.setStepIndex(count); step.setHostname(step.getHostname()); step.setSimplePath(step.getSimplePath()); * step.setMethod(step.getMethod()); step.setMimetype(step.getMimetype()); step.setProtocol(step.getProtocol()); * step.setType(step.getType()); step.setComments(step.getComments()); step.setName(step.getName()); * step.setResponse(step.getResponse()); step.setLoggingKey(step.getLoggingKey()); * step.setReqFormat(step.getReqFormat()); // step.setScriptGroup(e.getScriptGroup()); * step.setOnFail(step.getOnFail()); * * step.setData(getRequestData(step, step.getData())); step.setRequestheaders(getRequestData(step, * step.getRequestheaders())); step.setResponseheaders(getRequestData(step, step.getResponseheaders())); * step.setQueryStrings(getRequestData(step, step.getQueryStrings())); step.setPostDatas(getRequestData(step, * step.getPostDatas())); step.setResponseData(getRequestData(step, step.getResponseData())); * step.setRequestCookies(getRequestData(step, step.getRequestCookies())); * step.setResponseCookies(getRequestData(step, step.getResponseCookies())); return step; } */ private static Set<RequestData> copyRequestData(Set<RequestData> setData) { Set<RequestData> rd = null; if (null != setData) { rd = new HashSet<RequestData>(); for (RequestData d : setData) { RequestData newData = new RequestData(); newData.setKey(d.getKey()); newData.setType(d.getType()); newData.setValue(d.getValue()); rd.add(newData); } } return rd; } public static ScriptStep copyScriptStep(ScriptStep step) { ScriptStep ret = new ScriptStep(); ret.setComments(step.getComments()); ret.setData(copyRequestData(step.getData())); ret.setHostname(step.getHostname()); ret.setMethod(step.getMethod()); ret.setMimetype(step.getMimetype()); ret.setName(step.getName()); ret.setOnFail(step.getOnFail()); ret.setPayload(step.getPayload()); ret.setPostDatas(copyRequestData(step.getPostDatas())); ret.setProtocol(step.getProtocol()); ret.setQueryStrings(copyRequestData(step.getQueryStrings())); ret.setReqFormat(step.getReqFormat()); ret.setRequestCookies(copyRequestData(step.getRequestCookies())); ret.setRequestheaders(copyRequestData(step.getRequestheaders())); ret.setRespFormat(step.getRespFormat()); ret.setResponse(step.getResponse()); ret.setResponseCookies(step.getResponseCookies()); ret.setResponseData(copyRequestData(step.getResponseData())); ret.setResponseheaders(copyRequestData(step.getResponseheaders())); ret.setResult(step.getResult()); ret.setSimplePath(step.getSimplePath()); ret.setType(step.getType()); ret.setUrl(step.getUrl()); ret.setUuid(UUID.randomUUID().toString()); ret.setLabel(getStepLabel(ret)); return ret; } public static long calculateStepDuration(ScriptStep step, Map<String, String> variables, TankConfig config) { long result = 0; try { if (step.getType().equalsIgnoreCase("request")) { result = config.getAgentConfig().getRange(step.getMethod()).getRandomValueWithin(); } else if (step.getType().equalsIgnoreCase("variable")) { Set<RequestData> data = step.getData(); for (RequestData requestData : data) { variables.put(requestData.getKey(), requestData.getValue()); } } else if (step.getType().equalsIgnoreCase("thinkTime")) { String min = "0"; String max = "0"; Set<RequestData> setData = step.getData(); if (null != setData) { Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); if (d.getKey().contains("min")) { min = d.getValue(); } else if (d.getKey().contains("max")) { max = d.getValue(); } } } if (ValidationUtil.isAnyVariable(min)) { String s = (String) variables.get(ValidationUtil.removeAllVariableIdentifier(min)); min = s != null ? s : min; } if (ValidationUtil.isAnyVariable(max)) { String s = (String) variables.get(ValidationUtil.removeAllVariableIdentifier(max)); max = s != null ? s : max; } result = ((TimeUtil.parseTimeString(max) + TimeUtil.parseTimeString(min)) / 2); } else if (step.getType().equalsIgnoreCase("sleep")) { Set<RequestData> setData = step.getData(); if (null != setData) { Iterator<RequestData> iter = setData.iterator(); while (iter.hasNext()) { RequestData d = iter.next(); if (d.getKey().equalsIgnoreCase("time")) { String time = d.getValue(); if (ValidationUtil.isAnyVariable(time)) { String s = (String) variables.get(ValidationUtil.removeAllVariableIdentifier(time)); time = s != null ? s : time; } result = TimeUtil.parseTimeString(time); break; } } } } else { result = config.getAgentConfig().getRange("process").getRandomValueWithin(); } } catch (Exception e) { LOG.error("Error calculating step time: " + e); } return result; } public static String getDataFileUse(ScriptStep step) { String ret = null; if (step.getType().equalsIgnoreCase("variable")) { String value = step.getData().iterator().next().getValue(); Matcher m = csvPattern.matcher(value); while (m.find()) { // find next match String args = m.group(1).trim(); String[] split = args.split(","); ret = TankConstants.DEFAULT_CSV_FILE_NAME; if (split.length > 0) { String test = split[0].trim(); if (StringUtils.isNotBlank(test) && !NumberUtils.isDigits(test)) { ret = test; } } } } return ret; } }