All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ats.script.actions.ActionCallscript Maven / Gradle / Ivy

The newest version!
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */

package com.ats.script.actions;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.ats.AtsSingleton;
import com.ats.driver.AtsManager;
import com.ats.element.SearchedElement;
import com.ats.element.test.TestElement;
import com.ats.executor.ActionStatus;
import com.ats.executor.ActionTestScript;
import com.ats.executor.AtsCallscriptLogs;
import com.ats.executor.channels.Channel;
import com.ats.executor.scripts.AtsCallSubscriptException;
import com.ats.executor.scripts.AtsCallSubscriptJavascript;
import com.ats.executor.scripts.AtsCallSubscriptPython;
import com.ats.executor.scripts.AtsCallSubscriptScript;
import com.ats.generator.variables.CalculatedValue;
import com.ats.generator.variables.ConditionalValue;
import com.ats.generator.variables.TableSplit;
import com.ats.generator.variables.Variable;
import com.ats.generator.variables.parameter.Parameter;
import com.ats.generator.variables.parameter.ParameterDataFile;
import com.ats.generator.variables.parameter.ParameterList;
import com.ats.recorder.VisualAction;
import com.ats.script.Project;
import com.ats.script.Script;
import com.ats.script.ScriptHeader;
import com.ats.script.ScriptLoader;
import com.ats.tools.Utils;
import com.ats.tools.logger.MessageCode;
import com.ats.tools.logger.levels.AtsFailError;
import com.ats.tools.report.SuitesReportItem;
import com.google.gson.JsonObject;

public class ActionCallscript extends ActionReturnVariableArray implements IActionStoppable {

	public static final String SCRIPT_LABEL = "subscript";
	public static final String CALLSCRIPT_LABEL = "callscript";
	public static final String CALL_SUBSCRIPT_LABEL = "call-subscript";

	public static final Predicate PREDICATE_OLD = g -> SCRIPT_LABEL.equals(g);
	public static final Predicate PREDICATE = g -> CALLSCRIPT_LABEL.equals(g);
	public static final Predicate PREDICATE_NEW = g -> CALL_SUBSCRIPT_LABEL.equals(g);

	public static final String RANDOM_LABEL = "rnd";
	private static final String RANDOM2_LABEL = "random";
	public static final String SUITE_LABEL = "suite";
	public static final String RANGE_LABEL = "range";
	public static final String IF_LABEL = "if(";
	private static final String LOOP_LABEL = "loop";
	private static final String TABLE_LABEL = "table";

	public static final Pattern LOOP_REGEXP = Pattern.compile(LOOP_LABEL + " ?\\((\\d+)\\)", Pattern.CASE_INSENSITIVE);

	public static final String ASSETS_PROTOCOLE = Project.ASSETS_FOLDER + ":///";

	public static final String FILE_PROTOCOLE = "file://";
	public static final String HTTP_PROTOCOLE = "http://";
	public static final String HTTPS_PROTOCOLE = "https://";
	public static final String JAR_PROTOCOLE = "jar";

	public static final String JAVASCRIPT_PROTOCOLE = "js://";
	public static final String JAVA_PROTOCOLE = "java://";
	public static final String PYTHON_PROTOCOLE = "py://";
	public static final String CS_PROTOCOLE = "cs://";

	private CalculatedValue name;
	private int type = -1;

	private SearchedElement searchElement;

	private ArrayList scriptVariables;

	private ParameterList parameters;

	private int loop = 1;

	private CalculatedValue parameterFilePath;
	private boolean suite = false;
	private String range = null;
	private boolean random = false;

	private JsonObject paramsData;

	private ConditionalValue condition;
	private TableSplit tableSplit;

	private String calledScript = "";

	//---------------------------------------------------------------------------------------------------------------------------------
	// Constructors
	//---------------------------------------------------------------------------------------------------------------------------------

	public ActionCallscript() {}

	public ActionCallscript(ScriptLoader script, ArrayList options, String name, String[] parameters, String[] returnValue, String csvFilePath, ArrayList dataArray) {

		super(script);
		setName(new CalculatedValue(script, name));

		if (csvFilePath != null) {
			setParameterFilePath(new CalculatedValue(script, csvFilePath));
			if (dataArray != null && dataArray.size() > 0) {
				final String l = dataArray.remove(0);
				if (l.contains(RANDOM_LABEL) || l.contains(RANDOM2_LABEL)) {
					random = true;
				} else {
					range = l;
				}
			}
		} else if (dataArray != null && dataArray.size() > 0) {

			searchElement = new SearchedElement(script, dataArray);

		} else {
			if (parameters.length > 0) {
				final String firstParam = parameters[0].trim();
				if (!setParameterFilePathData(firstParam)) {
					final ArrayList paramsValues = new ArrayList<>();
					for (String param : parameters) {

						param = param.replaceAll("\n", ",");

						final Matcher match = LOOP_REGEXP.matcher(param);
						if (match.find()) {
							loop = Utils.string2Int(match.group(1), 1);
						} else {
							paramsValues.add(new CalculatedValue(script, param.trim()));
						}
					}
					this.setParameters(paramsValues);
				}
			}
		}

		if (returnValue.length > 0 && loop == 1) {
			final ArrayList variableValues = new ArrayList<>();
			for (String varName : returnValue) {
				variableValues.add(script.getVariable(varName.trim(), true));
			}
			setVariables(variableValues);
		}

		if (options.size() > 0) {
			final String option = options.get(0);
			int operatorIndex = option.indexOf(ConditionalValue.EQUALS);
			if (operatorIndex > 1) {
				condition = new ConditionalValue(script, option.substring(0, operatorIndex).trim(), option.substring(operatorIndex + 1).trim(), ConditionalValue.VALUE_EQUALS);
			} else {
				operatorIndex = option.indexOf(ConditionalValue.DIFFERENT);
				if (operatorIndex > 1) {
					condition = new ConditionalValue(script, option.substring(0, operatorIndex).trim(), option.substring(operatorIndex + 2).trim(), ConditionalValue.VALUE_NOT_EQUALS);
				}
			}
		}
	}
	
	public ActionCallscript(ScriptLoader script, String name, ArrayList options, String[] parameters, String[] returnValue, String csvFilePath, ArrayList dataArray, String tableSplit) {
		this(script, name, options, parameters, returnValue, csvFilePath, dataArray);
		if(tableSplit != null) {
			setTableSplit(new TableSplit(tableSplit, getParameters()));
		}
	}

	public ActionCallscript(ScriptLoader script, String name, ArrayList options, String[] parameters, String[] returnValue, String csvFilePath, ArrayList dataArray) {

		super(script);
		setName(new CalculatedValue(script, name));

		if (csvFilePath != null) {
			setParameterFilePath(new CalculatedValue(script, csvFilePath));
		} else if (dataArray != null && dataArray.size() > 0) {

			searchElement = new SearchedElement(script, dataArray);

		} else {
			if (parameters.length > 0) {
				final String firstParam = parameters[0].trim();
				if (!setParameterFilePathData(firstParam)) {
					final ArrayList paramsValues = new ArrayList<>();
					for (String param : parameters) {

						param = param.replaceAll("\n", ",");

						paramsValues.add(new CalculatedValue(script, param.trim()));

					}
					this.setParameters(paramsValues);
				}
			}
		}

		options.forEach(o -> parseOptions(script, o.trim()));

		if (returnValue.length > 0 && loop == 1) {
			final ArrayList variableValues = new ArrayList<>();
			for (String varName : returnValue) {
				variableValues.add(script.getVariable(varName.trim(), true));
			}
			setVariables(variableValues);
		}
	}

	public ActionCallscript(Script script, CalculatedValue name) {
		super(script);
		this.setName(name);
	}

	public ActionCallscript(Script script, CalculatedValue name, SearchedElement element) {
		this(script, name);
		this.setSearchElement(element);
	}

	public ActionCallscript(Script script, CalculatedValue name, CalculatedValue[] parameters) {
		this(script, name);
		this.setParameters(new ArrayList<>(Arrays.asList(parameters)));
	}

	public ActionCallscript(Script script, CalculatedValue name, Variable... variables) {
		this(script, name);
		this.setVariables(new ArrayList<>(Arrays.asList(variables)));
	}
	
	public ActionCallscript(Script script, CalculatedValue name, SearchedElement element, Variable... variables) {
		this(script, name);
		this.setSearchElement(element);
		this.setVariables(new ArrayList<>(Arrays.asList(variables)));
	}

	public ActionCallscript(Script script, CalculatedValue name, CalculatedValue[] parameters, Variable... variables) {
		this(script, name);
		this.setParameters(new ArrayList<>(Arrays.asList(parameters)));
		this.setVariables(new ArrayList<>(Arrays.asList(variables)));
	}

	public ActionCallscript(Script script, CalculatedValue name, boolean random, boolean suite, CalculatedValue csvFilePath, String range) {
		this(script, name);
		this.setRandom(random);
		this.setSuite(suite);
		this.setParameterFilePath(csvFilePath);
		this.setRange(range);
	}

	public ActionCallscript(Script script, CalculatedValue name, boolean random, boolean suite, CalculatedValue csvFilePath, String range, Variable... variables) {
		this(script, name);
		this.setRandom(random);
		this.setSuite(suite);
		this.setParameterFilePath(csvFilePath);
		this.setRange(range);
		this.setVariables(new ArrayList<>(Arrays.asList(variables)));
	}

	public ActionCallscript(Script script, CalculatedValue name, CalculatedValue[] parameters, int loop) {
		this(script, name, parameters);
		this.setLoop(loop);
	}

	public ActionCallscript(Script script, CalculatedValue name, int loop) {
		this(script, name);
		this.setLoop(loop);
	}

	public ActionCallscript(Script script, CalculatedValue name, TableSplit splitter) {
		this(script, name);
		this.setTableSplit(splitter);
	}

	public ActionCallscript(Script script, CalculatedValue name, TableSplit splitter, Variable... variables) {
		this(script, name);
		this.setTableSplit(splitter);
		this.setVariables(new ArrayList<>(Arrays.asList(variables)));
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	// End of constructors
	//---------------------------------------------------------------------------------------------------------------------------------

	@Override
	public boolean isStop() {
		return true;
	}

	private void parseOptions(Script script, String value) {
		if (RANDOM_LABEL.equals(value)) {
			random = true;
		} else if (SUITE_LABEL.equals(value)) {
			suite = true;
		} else if (value.startsWith(IF_LABEL) && value.endsWith(")")) {

			final String conditionCode = value.substring(3, value.length() - 1);
			int operatorIndex = conditionCode.indexOf(ConditionalValue.VALUE_EQUALS);

			if (operatorIndex > 1) {
				condition = new ConditionalValue(script, conditionCode.substring(0, operatorIndex).trim(), conditionCode.substring(operatorIndex + 2).trim(), ConditionalValue.VALUE_EQUALS);
			} else {
				operatorIndex = conditionCode.indexOf(ConditionalValue.VALUE_NOT_EQUALS);
				if (operatorIndex > 1) {
					condition = new ConditionalValue(script, conditionCode.substring(0, operatorIndex).trim(), conditionCode.substring(operatorIndex + 2).trim(), ConditionalValue.VALUE_NOT_EQUALS);
				}
			}

		} else {

			final String[] optionData = value.split("=");
			if (optionData.length == 2) {

				final String optionType = optionData[0].trim();
				final String optionValue = optionData[1].trim();

				if (RANGE_LABEL.equals(optionType)) {
					if (parameterFilePath != null) {
						range = optionValue;
					}
				} else if (LOOP_LABEL.equals(optionType)) {
					loop = Utils.string2Int(optionValue, 1);
				}else if (TABLE_LABEL.equals(optionType)) {
					if(parameters != null) {
						setTableSplit(new TableSplit(optionValue, parameters));
					}
				}
			}
		}
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	// Logs
	//---------------------------------------------------------------------------------------------------------------------------------

	public static String getScriptLog(String testName, int line, JsonObject log) {

		log.addProperty("name", testName);
		log.addProperty("line", line);

		final StringBuilder sb =
				new StringBuilder("Subscript")
				.append(" -> ")
				.append(log.toString());

		return sb.toString();
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------------------

	public boolean isSubscriptCalled(String scriptName) {
		return name.getCalculated().equals(scriptName);
	}

	private boolean setParameterFilePathData(String value) {
		if (value != null) {
			if (value.startsWith(ASSETS_PROTOCOLE) || value.startsWith(FILE_PROTOCOLE) || value.startsWith(HTTP_PROTOCOLE) || value.startsWith(HTTPS_PROTOCOLE)) {
				setParameterFilePath(new CalculatedValue(script, value));
				return true;
			}
		}
		return false;
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	// Code Generator
	//---------------------------------------------------------------------------------------------------------------------------------

	@Override
	public StringBuilder getJavaCode() {

		final StringBuilder codeBuilder = super.getJavaCode();

		codeBuilder.append(name.getJavaCode());

		if (parameterFilePath != null) {
			codeBuilder.append(", ")
			.append(random)
			.append(", ")
			.append(suite)
			.append(", ")
			.append(parameterFilePath.getJavaCode())
			.append(", ")
			;

			if (range == null || range.isEmpty()) {
				codeBuilder.append("null");
			} else {
				codeBuilder.append("\"")
				.append(range)
				.append("\"");
			}

		} else if (searchElement != null) {
			codeBuilder.append(", ")
			.append(searchElement.getJavaCode());
		} else if (tableSplit != null) {
			codeBuilder.append(", ")
			.append(tableSplit.getJavaCode());
		} else {
			if (parameters != null) {
				parameters.appendJavaCode(codeBuilder);
			}

			if (loop > 1) {
				codeBuilder.append(", ")
				.append(loop);
			}
		}

		if (getVariables() != null) {
			final StringJoiner joiner = new StringJoiner(", ");
			for (Variable variable : getVariables()) {
				joiner.add(variable.getName());
			}
			codeBuilder.append(", ")
			.append(joiner.toString());
		}

		codeBuilder.append(")");

		if (condition != null) {
			return condition.getJavaCode(codeBuilder, getLine());
		}

		return codeBuilder;
	}

	@Override
	public ArrayList getKeywords() {
		final ArrayList keywords = super.getKeywords();
		keywords.add(name.getData());
		if (parameterFilePath != null) {
			keywords.add(parameterFilePath.getKeywords());
		}
		if (searchElement != null) {
			keywords.addAll(searchElement.getKeywords());
		}
		return keywords;
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------------------

	@Override
	public Element getXmlElement(Document document, ScriptHeader header, int index, String errorText) {
		Element e = super.getXmlElement(document, header, index, errorText);
		e.appendChild(document.createElement("value")).setTextContent(calledScript);

		final Element dataJson = document.createElement(DATA_JSON);
		e.appendChild(dataJson);

		Element param = document.createElement("parameter");
		param.setAttribute("type", "asset");

		if (parameterFilePath != null) {
			param.setAttribute("value", parameterFilePath.getCalculated());
		}

		dataJson.appendChild(param);

		return e;
	}

	@Override
	public VisualAction getVisualAction() {
		return new VisualAction(this, timeLine, calledScript, parameterFilePath);
	}

	//---------------------------------------------------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------------------

	private URL loopAssetsFiles(File[] files, String path) {
		if(files != null) {
			final int count = files.length;
			for(int i=0; i clazz, 
			ActionTestScript topScript,
			String scriptName,
			String scriptCode) 
					throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {

		final ActionTestScript ats = clazz.getDeclaredConstructor().newInstance();

		if(scriptCode != null && ats instanceof AtsCallSubscriptScript) {
			((AtsCallSubscriptScript)ats).setScripCode(scriptCode);
		}

		ats.setTopScript(topScript, scriptName);
		return ats;
	}

	private String getScriptCode(ActionTestScript ts, String testName, String scriptType) {

		final int lastDot = calledScript.lastIndexOf(".");
		final String scriptExtension = calledScript.substring(lastDot);
		final String scriptPath = calledScript.substring(0, lastDot).replace(".", "/");
		
		String result = null;
		final String scriptSourcePath = Paths.get("").toAbsolutePath().resolve(Project.SRC_FOLDER).resolve("main").resolve(scriptType).resolve(scriptPath + scriptExtension).toString();

		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(scriptSourcePath);
		} catch (FileNotFoundException e) {}

		if(inputStream == null) {
			inputStream = getClass().getClassLoader().getResourceAsStream(AtsManager.SCRIPTS_FOLDER_URL + "/" + scriptType + "/" + calledScript);
		}

		if(inputStream == null) {
			
			final String errorMessage = "Script file not found -> " + scriptSourcePath;
			status.setError(MessageCode.SCRIPT_NOT_FOUND, errorMessage);
			status.endDuration();

			ts.callScriptFailed(testName, line, MessageCode.SCRIPT_NOT_FOUND, errorMessage);
			
			throw new AtsCallSubscriptException(errorMessage);
			
		}else {
			try {
				result = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
				inputStream.close();
			} catch (IOException e) {}

			return result;
		}

	}

	@Override
	public String execute(ActionTestScript ts, String testName, int line, int tryNum) {

		super.execute(ts, testName, line, 0);
		status.setNoError();

		calledScript = name.getCalculated().replace("\n", "");

		AtsCallscriptLogs calledScriptLogs = null;
		String scriptCode = null;

		Class clazz = null;

		if(calledScript.startsWith(JAVASCRIPT_PROTOCOLE) || calledScript.startsWith(PYTHON_PROTOCOLE) || calledScript.startsWith(CS_PROTOCOLE)) {

			if(calledScript.startsWith(JAVASCRIPT_PROTOCOLE)){
				calledScript = calledScript.substring(JAVASCRIPT_PROTOCOLE.length()) + ".js";

				scriptCode = getScriptCode(ts, testName, "javascript");

				clazz = AtsSingleton.getInstance().loadTestScriptClass(status, AtsCallSubscriptJavascript.class.getCanonicalName());
				calledScriptLogs = new AtsCallscriptLogs();

			}else if(calledScript.startsWith(PYTHON_PROTOCOLE)){
				calledScript = calledScript.substring(PYTHON_PROTOCOLE.length()) + ".py";

				scriptCode = getScriptCode(ts, testName, "python");

				clazz = AtsSingleton.getInstance().loadTestScriptClass(status, AtsCallSubscriptPython.class.getCanonicalName());
				calledScriptLogs = new AtsCallscriptLogs();
			}

		}else {
			if(calledScript.startsWith(JAVA_PROTOCOLE)) {
				calledScript = calledScript.substring(JAVA_PROTOCOLE.length());
				calledScriptLogs = new AtsCallscriptLogs();
			}
			clazz = AtsSingleton.getInstance().loadTestScriptClass(status, calledScript);
		}

		if(!status.isPassed()) {
			ts.callScriptFailed(testName, line, status.getCode(), status.getFailMessage());
			return null;
		}

		if(getVariables() != null) {
			getVariables().forEach(v -> v.clean());
		}

		getCurrentChannel().updateVisualCallScript(calledScript, ts.getRecorder(), this, testName, line);

		addParamsToData(ts);

		final ActionTestScript topScript = ts.getTopScript();

		try {

			if (parameterFilePath != null) {

				final String csvPath = parameterFilePath.getCalculated().replace("\\", "/");
				URL csvUrl = null;

				if (csvPath.startsWith(ASSETS_PROTOCOLE)) {

					String csvFilePath = csvPath.replace(ASSETS_PROTOCOLE, "");
					csvUrl = getAssetDataFile(csvFilePath);

					if(csvUrl == null) {
						csvFilePath = Project.ASSETS_FOLDER + "/" + csvFilePath;
						csvUrl = getClass().getClassLoader().getResource(csvFilePath);
						if (csvUrl == null) {
							csvUrl = getClass().getClassLoader().getResource(csvFilePath + ".csv");
							if (csvUrl == null) {
								csvUrl = getClass().getClassLoader().getResource(csvFilePath + ".json");
							}
						}
					}

				} else {
					try {
						csvUrl = new URI(csvPath).toURL();
					} catch (MalformedURLException | URISyntaxException ignored) {}
				}

				getCurrentChannel().updateRecorderFilePathData(ts, calledScript, paramsData, csvPath);

				if (csvUrl == null) {

					condition = null;

					final String errorMessage = "Parameter data file not found -> " + csvPath;
					status.setError(ActionStatus.FILE_NOT_FOUND, errorMessage);
					status.endDuration();

					ts.callScriptFailed(testName, line, ActionStatus.FILE_NOT_FOUND, errorMessage);

					return null;

				} else {

					if (csvPath.startsWith(FILE_PROTOCOLE)) {
						try {
							final File f = new File(csvUrl.toURI());
							if (!f.isFile()) {

								final String errorMessage = "URL path is not a file -> " + csvPath;
								status.setError(ActionStatus.FILE_NOT_FOUND, errorMessage + "\n");
								ts.callScriptFailed(testName, line, ActionStatus.FILE_NOT_FOUND, errorMessage);
							}
						} catch (IllegalArgumentException | URISyntaxException e1) {

							final String errorMessage = "URL path is not valid -> " + e1;
							status.setError(ActionStatus.FILE_NOT_FOUND, errorMessage + "\n");

							ts.callScriptFailed(testName, line, ActionStatus.FILE_NOT_FOUND, errorMessage);
						}
					}
				}

				final ParameterDataFile data = Utils.loadData(status, csvUrl);
				if (status.isPassed()) {

					String csvAbsoluteFilePath = null;
					try {
						if (csvPath.startsWith(HTTP_PROTOCOLE) || csvPath.startsWith(HTTPS_PROTOCOLE)) {
							csvAbsoluteFilePath = csvUrl.toString();
						}else if(JAR_PROTOCOLE.equals(csvUrl.getProtocol())) {
							csvAbsoluteFilePath = csvUrl.toString();
						} else {
							csvAbsoluteFilePath = new File(csvUrl.toURI()).getAbsolutePath();
						}

					} catch (URISyntaxException e) {
					}

					getCurrentChannel().updateRecorderFilePathData(ts, calledScript, paramsData, csvPath);

					final ArrayList selectedIndexes = new ArrayList<>();

					if (range != null) {
						final String[] rangeData = range.split(";");
						for (String singleRange : rangeData) {

							final String[] singleRangeData = singleRange.split("-");

							if (singleRangeData.length > 1) {

								int firstIndex = Utils.string2Int(singleRangeData[0], 0);
								int lastIndex = Utils.string2Int(singleRangeData[1], 0);

								if (firstIndex > 0 && lastIndex > 0) {
									if (firstIndex == lastIndex) {
										selectedIndexes.add(firstIndex);
									} else if (firstIndex < lastIndex) {
										for (int i = firstIndex; i <= lastIndex; i++) {
											selectedIndexes.add(i);
										}
									}
								}
							} else if (singleRangeData.length == 1) {
								int mainIndex = Utils.string2Int(singleRangeData[0], 0);
								if (mainIndex > 0) {
									selectedIndexes.add(mainIndex);
								}
							}
						}
					}

					final ArrayList selectedParameters = new ArrayList<>();

					if (!selectedIndexes.isEmpty()) {
						for (int index : selectedIndexes) {
							if (index <= data.getData().size()) {
								ParameterList params = data.getData().get(index - 1);
								selectedParameters.add(params);
							}
						}
					} else {
						selectedParameters.addAll(data.getData());
					}

					if (random) {
						ParameterList randomParam = selectedParameters.get((int) (Math.random() * selectedParameters.size()));
						selectedParameters.clear();
						selectedParameters.add(randomParam);
					}

					final int iterationsCount = selectedParameters.size();
					int iteration = 1;

					if (suite) {

						final Path outputDirectory = topScript.getSuiteOutputPath().getParent();
						final String suiteName = getSuiteName(1, outputDirectory, calledScript);

						topScript.stopRecorder();

						final Map suiteParameters = topScript.getTestExecutionVariables();
						suiteParameters.put(SuitesReportItem.CALLSCRIPT_ITERATION, testName + ":" + line);
						suiteParameters.put(SuitesReportItem.CALLSCRIPT_PARAMETER_FILE, csvPath);
						suiteParameters.putAll(AtsSingleton.getInstance().getGlobalVariables());

						final XmlSuite suite = new XmlSuite();
						suite.setName(suiteName);
						suite.setParameters(suiteParameters);

						for (ParameterList params : selectedParameters) {

							final XmlTest xmlTest = new XmlTest(suite);
							xmlTest.setName("iter" + iteration);
							xmlTest.addParameter(SuitesReportItem.ITERATION_PROPERTY, String.valueOf(iteration));

							int loop = 0;

							for (Parameter param : params.getList()) {
								param.updateCalculated(ts);
								xmlTest.addParameter("#" + loop, param.getCalculated());
								xmlTest.addParameter(param.getName(), param.getCalculated());
								loop++;
							}

							xmlTest.setXmlClasses(new ArrayList<>(Arrays.asList(new XmlClass(calledScript))));

							iteration++;
						}

						suite.setVerbose(topScript.getVerbosity());

						final TestNG tng = new TestNG();
						tng.setUseDefaultListeners(false);
						tng.addListener(new TestListenerAdapter());

						tng.setOutputDirectory(outputDirectory.toAbsolutePath().toString());
						tng.setXmlSuites(new ArrayList<>(Arrays.asList(suite)));

						tng.setDefaultSuiteName("Callscript as a suite -> " + suiteName);
						tng.run();

						topScript.setTestList(tng.getTestListeners());

					} else {

						final Method tc = clazz.getDeclaredMethod(ActionTestScript.MAIN_TEST_FUNCTION, new Class[]{});

						final ActionTestScript ats = getNewAtsInstance(clazz, topScript, calledScript, scriptCode);
						String[] returns = null;

						for (ParameterList row : selectedParameters) {
							callScriptWithParametersFile(tc, ats, ts, testName, line, row, getVariables(), iteration, iterationsCount, calledScript, csvAbsoluteFilePath);
							iteration++;

							returns = ats.getReturnValues();
						}

						status.setData(returns);
					}
				}else {
					final String errorMessage = "URL path is not valid -> " + csvPath;
					status.setError(ActionStatus.FILE_NOT_FOUND, errorMessage + "\n");
					ts.callScriptFailed(testName, line, ActionStatus.FILE_NOT_FOUND, errorMessage);
				}

			} else {

				final ActionTestScript ats = getNewAtsInstance(clazz, topScript, calledScript, scriptCode);
				final Method mainFunc = clazz.getDeclaredMethod(ActionTestScript.MAIN_TEST_FUNCTION, new Class[]{});

				if (searchElement != null) {

					final List data = getCallScriptElementData(ts, AtsSingleton.getInstance().getCurrentChannel(), searchElement);
					final int iterationMax = data.size();

					if(data.size() == 0) {
						final String errorMessage = "callscript failed: no element found";
						status.setError(ActionStatus.OBJECT_NOT_FOUND, errorMessage + "\n");
						ts.callScriptFailed(testName, line, ActionStatus.OBJECT_NOT_FOUND, errorMessage);
						
						throw new AtsCallSubscriptException(errorMessage);
					}else {
						for (int iteration = 1; iteration <= iterationMax; iteration++) {

							ats.initCalledScript(
									ts,
									testName, 
									line, 
									data.get(iteration - 1), 
									getVariables(), 
									iteration, 
									iterationMax, 
									calledScript, LOOP_LABEL,
									null);

							mainFunc.invoke(ats);
						}
					}

				}else if(tableSplit != null) {

					final List data = tableSplit.getData();
					final int iterationMax = data.size();

					for (int iteration = 1; iteration <= iterationMax; iteration++) {

						ats.initCalledScript(
								ts,
								testName, 
								line, 
								data.get(iteration - 1), 
								getVariables(), 
								iteration, 
								iterationMax, 
								calledScript, TABLE_LABEL,
								null);

						mainFunc.invoke(ats);
					}

				} else {
					for (int iteration = 1; iteration <= loop; iteration++) {
						ats.initCalledScript(ts, testName, line, parameters, getVariables(), iteration, loop, calledScript, LOOP_LABEL, null);
						mainFunc.invoke(ats);
					}
				}

				status.setData(ats.getReturnValues());
			}

		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
				NoSuchMethodException | SecurityException e) {

			ts.callScriptFailed(testName, line, -99, e.getMessage());

		} catch (InvocationTargetException e) {
			if (e.getTargetException() instanceof AtsFailError) {
				
				final AtsFailError target = (AtsFailError) e.getTargetException();
				ts.callScriptFailed(testName, line, -99, target.getInfo());

				status.setError(ActionStatus.ATS_ERROR, target.getFullMessage(ts.getLogger()));
				
			} else if(e.getTargetException() instanceof AtsCallSubscriptException) {

				final AtsCallSubscriptException target = (AtsCallSubscriptException) e.getTargetException();
				status.setError(ActionStatus.JAVA_EXCEPTION, target.getMessage() + "\n");

			} else {
				
				final String errorMessage = Utils.getCauseStackTraceString(e, "");
				status.setError(ActionStatus.JAVA_EXCEPTION, errorMessage + "\n");
				
				ts.callScriptFailed(testName, line, ActionStatus.JAVA_EXCEPTION, errorMessage);
			}
		}

		condition = null;
		status.endDuration();

		if(calledScriptLogs != null) {
			return calledScriptLogs.terminate();
		}

		return null;
	}

	private static String getSuiteName(int i, Path folder, String name) {
		final String suiteName = name + "-suite" + i;
		if (folder.resolve(suiteName).toFile().exists()) {
			return getSuiteName(i + 1, folder, name);
		} else {
			return suiteName;
		}
	}

	public static List getCallScriptElementData(ActionTestScript script, Channel channel, SearchedElement element) {

		int max = 10;

		TestElement testElement = new TestElement(script, channel, 10, p -> p > 0, element);
		while (max > 0 && testElement.getCount() == 0) {
			channel.sleep(500);
			testElement = new TestElement(script, channel, 10, p -> p > 0, element);
			max--;
		}

		channel.updateVisualAction(testElement);

		if (testElement.getCount() > 0) {
			return testElement.getTextData();
		}

		return Collections.emptyList();
	}

	private void callScriptWithParametersFile(
			Method mainFunc,
			ActionTestScript ats,
			ActionTestScript atsCaller,
			String testName,
			int line,
			ParameterList row,
			List variables,
			int iteration,
			int iterationsCount,
			String scriptName,
			String csvAbsoluteFilePath) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		row.updateCalculated(atsCaller);

		ats.initCalledScript(atsCaller, testName, line, row, variables, iteration, iterationsCount, scriptName, "dataFile", csvAbsoluteFilePath);

		mainFunc.invoke(ats);
	}

	@Override
	public StringBuilder getActionLogs(String scriptName, int scriptLine, JsonObject data) {
		data.addProperty("status", "terminated");
		return super.getActionLogs(scriptName, scriptLine, data);
	}

	public void addParamsToData(ActionTestScript ts) {

		if (paramsData == null) {
			paramsData = new JsonObject();
		}

		ParameterList paramsList = getParameters();

		if (paramsList != null && paramsList.getParametersSize() > 0) {
			String[] paramsArray = paramsList.getParameters();
			for (int ind = 0; ind < paramsList.getParametersSize(); ind++) {
				paramsData.addProperty(Integer.toString(ind), paramsArray[ind]);
			}
			getCurrentChannel().updateRecorderData(ts, calledScript, paramsData);
		}
	}

	//--------------------------------------------------------
	// getters and setters for serialization
	//--------------------------------------------------------

	public CalculatedValue getName() {
		return name;
	}

	public void setName(CalculatedValue name) {
		this.name = name;
	}

	@Override
	public void setVariables(ArrayList value) {
		if (value != null && value.size() > 0) {
			super.setVariables(value);
			//this.parameterFilePath = null;
			//this.loop = 1;
		}
	}

	public ParameterList getParameters() {
		return parameters;
	}

	public void setParameters(ParameterList value) {
		if (value != null && value.getParametersSize() > 0) {
			this.parameters = value;
			this.parameterFilePath = null;
		}
	}

	public void setParameters(ArrayList calcs) {
		parameters = new ParameterList(1);
		int i = 0;
		for (CalculatedValue calc : calcs) {
			parameters.addParameter(new Parameter(i, calc));
			i++;
		}
	}

	public int getLoop() {
		return loop;
	}

	public void setLoop(int loop) {

		if (loop <= 0) {
			loop = 1;
		}

		if (loop > 1) {
			this.parameterFilePath = null;
			//setVariables(null);
		}
		this.loop = loop;
	}

	public SearchedElement getSearchElement() {
		return searchElement;
	}

	public void setSearchElement(SearchedElement value) {
		this.searchElement = value;
	}

	public boolean isSuite() {
		return suite;
	}

	public void setSuite(boolean suite) {
		this.suite = suite;
	}

	public String getRange() {
		return range;
	}

	public void setRange(String value) {
		this.range = value;
	}

	public boolean isRandom() {
		return random;
	}

	public void setRandom(boolean random) {
		this.random = random;
	}

	public CalculatedValue getParameterFilePath() {
		return parameterFilePath;
	}

	public void setParameterFilePath(CalculatedValue value) {
		this.parameterFilePath = value;
		if (value != null) {
			this.parameters = null;
		}
	}

	public ConditionalValue getCondition() {
		return condition;
	}

	public void setCondition(ConditionalValue condition) {
		this.condition = condition;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public ArrayList getScriptVariables() {
		return scriptVariables;
	}

	public void setScriptVariables(ArrayList scriptVariable) {
		this.scriptVariables = scriptVariable;
	}

	public static StringBuilder getAtsCodeStr() {
		return new StringBuilder().append(SCRIPT_LABEL).append(" -> ");
	}

	public TableSplit getTableSplit() {
		return tableSplit;
	}

	public void setTableSplit(TableSplit value) {
		this.tableSplit = value;
		if (value != null) {
			this.parameters = null;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy