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

org.evosuite.symbolic.expr.ExpressionExecutor Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.symbolic.expr;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.StringTokenizer;

import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.evosuite.symbolic.expr.bv.IntegerBinaryExpression;
import org.evosuite.symbolic.expr.bv.IntegerComparison;
import org.evosuite.symbolic.expr.bv.IntegerConstant;
import org.evosuite.symbolic.expr.bv.IntegerUnaryExpression;
import org.evosuite.symbolic.expr.bv.IntegerVariable;
import org.evosuite.symbolic.expr.bv.RealComparison;
import org.evosuite.symbolic.expr.bv.RealToIntegerCast;
import org.evosuite.symbolic.expr.bv.RealUnaryToIntegerExpression;
import org.evosuite.symbolic.expr.bv.StringBinaryComparison;
import org.evosuite.symbolic.expr.bv.StringBinaryToIntegerExpression;
import org.evosuite.symbolic.expr.bv.StringMultipleComparison;
import org.evosuite.symbolic.expr.bv.StringMultipleToIntegerExpression;
import org.evosuite.symbolic.expr.bv.StringToIntegerCast;
import org.evosuite.symbolic.expr.bv.StringUnaryToIntegerExpression;
import org.evosuite.symbolic.expr.fp.IntegerToRealCast;
import org.evosuite.symbolic.expr.fp.RealBinaryExpression;
import org.evosuite.symbolic.expr.fp.RealConstant;
import org.evosuite.symbolic.expr.fp.RealUnaryExpression;
import org.evosuite.symbolic.expr.fp.RealVariable;
import org.evosuite.symbolic.expr.reader.StringReaderExpr;
import org.evosuite.symbolic.expr.ref.GetFieldExpression;
import org.evosuite.symbolic.expr.ref.ReferenceConstant;
import org.evosuite.symbolic.expr.ref.ReferenceVariable;
import org.evosuite.symbolic.expr.str.IntegerToStringCast;
import org.evosuite.symbolic.expr.str.RealToStringCast;
import org.evosuite.symbolic.expr.str.StringBinaryExpression;
import org.evosuite.symbolic.expr.str.StringConstant;
import org.evosuite.symbolic.expr.str.StringMultipleExpression;
import org.evosuite.symbolic.expr.str.StringUnaryExpression;
import org.evosuite.symbolic.expr.str.StringVariable;
import org.evosuite.symbolic.expr.token.HasMoreTokensExpr;
import org.evosuite.symbolic.expr.token.NewTokenizerExpr;
import org.evosuite.symbolic.expr.token.NextTokenizerExpr;
import org.evosuite.symbolic.expr.token.StringNextTokenExpr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * returns the concrete evaluation for a given expression.
 * 
 * @author galeotti
 *
 */
public class ExpressionExecutor implements ExpressionVisitor {

	private static final long TRUE_VALUE = 1L;
	private static final long FALSE_VALUE = 0L;
	protected static final Logger log = LoggerFactory.getLogger(ExpressionExecutor.class);

	@Override
	public Object visit(IntegerBinaryExpression n, Void arg) {
		Long leftLong = (Long) n.getLeftOperand().accept(this, null);
		Long rightLong = (Long) n.getRightOperand().accept(this, null);

		long leftVal = leftLong.longValue();
		long rightVal = rightLong.longValue();

		Operator op = n.getOperator();
		switch (op) {

		case SHL:
			return leftVal << rightVal;
		case SHR:
			return leftVal >> rightVal;
		case USHR:
			return leftVal >>> rightVal;
		case AND:
		case IAND:
			return leftVal & rightVal;
		case OR:
		case IOR:
			return leftVal | rightVal;
		case XOR:
		case IXOR:
			return leftVal ^ rightVal;
		case DIV:
			return leftVal / rightVal;
		case MUL:
			return leftVal * rightVal;
		case MINUS:
			return leftVal - rightVal;
		case PLUS:
			return leftVal + rightVal;
		case REM:
			return leftVal % rightVal;
		case MAX:
			return Math.max(leftVal, rightVal);
		case MIN:
			return Math.min(leftVal, rightVal);

		default:
			log.warn("IntegerBinaryExpression: unimplemented operator: " + op);
			return null;
		}

	}

	@Override
	public Object visit(IntegerComparison n, Void arg) {
		log.warn("IntegerComparison.execute() invokation");
		throw new IllegalStateException("This method should not be invoked");
	}

	@Override
	public Object visit(IntegerConstant n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(IntegerUnaryExpression n, Void arg) {

		Long longObject = (Long) n.getOperand().accept(this, null);

		long leftVal = longObject.longValue();

		Operator op = n.getOperator();
		switch (op) {

		case NEG:
			return -leftVal;
		case ABS:
			return Math.abs(leftVal);
		case GETNUMERICVALUE:
			return (long) Character.getNumericValue((char) leftVal);
		case ISLETTER:
			return Character.isLetter((char) leftVal) ? TRUE_VALUE : FALSE_VALUE;
		case ISDIGIT:
			return Character.isDigit((char) leftVal) ? TRUE_VALUE : FALSE_VALUE;

		default:
			log.warn("IntegerUnaryExpression: unimplemented operator: " + op);
			return null;
		}
	}

	@Override
	public Object visit(IntegerVariable n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(RealComparison n, Void arg) {
		log.warn("RealComparison.execute() invokation");
		throw new IllegalStateException("This method should not be invoked");
	}

	@Override
	public Object visit(RealToIntegerCast n, Void arg) {
		Double doubleObject = (Double) n.getArgument().accept(this, null);
		return doubleObject.longValue();
	}

	@Override
	public Object visit(RealUnaryToIntegerExpression n, Void arg) {
		Double doubleObject = (Double) n.getOperand().accept(this, null);
		double leftVal = doubleObject.doubleValue();

		Operator op = n.getOperator();
		switch (op) {

		case ROUND:
			return Math.round(leftVal);
		case GETEXPONENT:
			return (long) Math.getExponent(leftVal);

		default:
			log.warn("IntegerUnaryExpression: unimplemented operator: " + op);
			return null;
		}
	}

	@Override
	public Object visit(StringBinaryComparison n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		String second = (String) n.getRightOperand().accept(this, null);

		Operator op = n.getOperator();
		switch (op) {
		case EQUALSIGNORECASE:
			return first.equalsIgnoreCase(second) ? TRUE_VALUE : FALSE_VALUE;
		case EQUALS:
			return first.equals(second) ? TRUE_VALUE : FALSE_VALUE;
		case ENDSWITH:
			return first.endsWith(second) ? TRUE_VALUE : FALSE_VALUE;
		case CONTAINS:
			return first.contains(second) ? TRUE_VALUE : FALSE_VALUE;
		case PATTERNMATCHES:
			return second.matches(first) ? TRUE_VALUE : FALSE_VALUE;
		case APACHE_ORO_PATTERN_MATCHES: {
			Perl5Matcher matcher = new Perl5Matcher();
			Perl5Compiler compiler = new Perl5Compiler();
			Pattern pattern;
			try {
				pattern = compiler.compile(first);
			} catch (MalformedPatternException e) {
				throw new RuntimeException(e);
			}
			return matcher.matches(second, pattern) ? TRUE_VALUE : FALSE_VALUE;

		}
		default:
			log.warn("StringComparison: unimplemented operator!" + op);
			return null;
		}

	}

	@Override
	public Object visit(StringBinaryToIntegerExpression n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		Object second = (Object) n.getRightOperand().accept(this, null);

		Operator op = n.getOperator();
		switch (op) {

		// returns Int
		case COMPARETO: {
			String string = (String) second;
			return (long) first.compareTo(string);
		}
		case COMPARETOIGNORECASE: {
			String string = (String) second;
			return (long) first.compareToIgnoreCase(string);
		}
		case INDEXOFC: {
			long ch = (Long) second;
			return (long) first.indexOf((char) ch);
		}
		case INDEXOFS: {
			String string = (String) second;
			return (long) first.indexOf(string);
		}
		case LASTINDEXOFC: {
			long ch = (Long) second;
			return (long) first.lastIndexOf((char) ch);
		}
		case LASTINDEXOFS: {
			String string = (String) second;
			return (long) first.lastIndexOf(string);
		}
		case CHARAT: {
			int indx = ((Long) second).intValue();
			return (long) first.charAt(indx);
		}
		default:
			log.warn("StringBinaryToIntegerExpression: unimplemented operator! Operator" + op.toString());
			return null;
		}

	}

	@Override
	public Object visit(StringMultipleComparison n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		String second = (String) n.getRightOperand().accept(this, null);
		ArrayList> other_v = n.getOther();

		Operator op = n.getOperator();
		switch (op) {
		case STARTSWITH:
			long start = (Long) other_v.get(0).accept(this, null);

			return first.startsWith(second, (int) start) ? TRUE_VALUE : FALSE_VALUE;

		case REGIONMATCHES:
			long frstStart = (Long) other_v.get(0).accept(this, null);
			long secStart = (Long) other_v.get(1).accept(this, null);
			long length = (Long) other_v.get(2).accept(this, null);
			long ignoreCase = (Long) other_v.get(3).accept(this, null);

			return first.regionMatches(ignoreCase != 0, (int) frstStart, second, (int) secStart, (int) length)
					? TRUE_VALUE : FALSE_VALUE;
		default:
			log.warn("StringMultipleComparison: unimplemented operator!");
			return null;
		}
	}

	@Override
	public Object visit(StringMultipleToIntegerExpression n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		Object second = (Object) n.getRightOperand().accept(this, null);
		ArrayList> other_v = n.getOther();

		long secLong, thrdLong;
		String secStr;

		Operator op = n.getOperator();
		switch (op) {

		// returns int
		case INDEXOFCI:
			secLong = (Long) second;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return (long) first.indexOf((int) secLong, (int) thrdLong);
		case INDEXOFSI:
			secStr = (String) second;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return (long) first.indexOf(secStr, (int) thrdLong);
		case LASTINDEXOFCI:
			secLong = (Long) second;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return (long) first.lastIndexOf((int) secLong, (int) thrdLong);
		case LASTINDEXOFSI:
			secStr = (String) second;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return (long) first.lastIndexOf(secStr, (int) thrdLong);

		default:
			log.warn("StringMultipleToIntegerExpression: unimplemented operator: " + op);
			return null;
		}
	}

	@Override
	public Object visit(StringToIntegerCast n, Void arg) {
		String str = (String) n.getArgument().accept(this, null);
		return Long.parseLong(str);

	}

	@Override
	public Object visit(StringUnaryToIntegerExpression n, Void arg) {
		String exOn = (String) n.getOperand().accept(this, null);

		Operator op = n.getOperator();
		switch (op) {

		case LENGTH:
			return (long) exOn.length();

		case IS_INTEGER: {
			try {
				Integer.parseInt(exOn);
				return TRUE_VALUE;
			} catch (NumberFormatException ex) {
				return FALSE_VALUE;
			}
		}

		default:
			log.warn("StringUnaryExpression: unimplemented operator!");
			return null;
		}
	}

	@Override
	public Object visit(IntegerToRealCast n, Void arg) {
		Long exprVal = (Long) n.getArgument().accept(this, null);
		return exprVal.doubleValue();
	}

	@Override
	public Object visit(RealBinaryExpression n, Void arg) {

		Double leftDouble = (Double) n.getLeftOperand().accept(this, null);
		Double rightDouble = (Double) n.getRightOperand().accept(this, null);

		double leftVal = leftDouble.doubleValue();
		double rightVal = rightDouble.doubleValue();

		Operator op = n.getOperator();
		switch (op) {

		case DIV:
			return leftVal / rightVal;
		case MUL:
			return leftVal * rightVal;
		case MINUS:
			return leftVal - rightVal;
		case PLUS:
			return leftVal + rightVal;
		case REM:
			return leftVal % rightVal;
		case ATAN2:
			return Math.atan2(leftVal, rightVal);
		case COPYSIGN:
			return Math.copySign(leftVal, rightVal);
		case HYPOT:
			return Math.hypot(leftVal, rightVal);
		case IEEEREMAINDER:
			return Math.IEEEremainder(leftVal, rightVal);
		case MAX:
			return Math.max(leftVal, rightVal);
		case MIN:
			return Math.min(leftVal, rightVal);
		case NEXTAFTER:
			return Math.nextAfter(leftVal, rightVal);
		case POW:
			return Math.pow(leftVal, rightVal);
		case SCALB:
			return Math.scalb(leftVal, (int) rightVal);

		default:
			log.warn("IntegerBinaryExpression: unimplemented operator: " + op);
			return null;
		}

	}

	@Override
	public Object visit(RealConstant n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(RealUnaryExpression n, Void arg) {
		Double doubleObject = (Double) n.getOperand().accept(this, null);
		double doubleVal = doubleObject.doubleValue();

		Operator op = n.getOperator();
		switch (op) {

		case ABS:
			return Math.abs(doubleVal);
		case ACOS:
			return Math.acos(doubleVal);
		case ASIN:
			return Math.asin(doubleVal);
		case ATAN:
			return Math.atan(doubleVal);
		case CBRT:
			return Math.cbrt(doubleVal);
		case CEIL:
			return Math.ceil(doubleVal);
		case COS:
			return Math.cos(doubleVal);
		case COSH:
			return Math.cosh(doubleVal);
		case EXP:
			return Math.exp(doubleVal);
		case EXPM1:
			return Math.expm1(doubleVal);
		case FLOOR:
			return Math.floor(doubleVal);
		case LOG:
			return Math.log(doubleVal);
		case LOG10:
			return Math.log10(doubleVal);
		case LOG1P:
			return Math.log1p(doubleVal);
		case NEG:
			return -doubleVal;
		case NEXTUP:
			return Math.nextUp(doubleVal);
		case RINT:
			return Math.rint(doubleVal);
		case SIGNUM:
			return Math.signum(doubleVal);
		case SIN:
			return Math.sin(doubleVal);
		case SINH:
			return Math.sinh(doubleVal);
		case SQRT:
			return Math.sqrt(doubleVal);
		case TAN:
			return Math.tan(doubleVal);
		case TANH:
			return Math.tanh(doubleVal);
		case TODEGREES:
			return Math.toDegrees(doubleVal);
		case TORADIANS:
			return Math.toRadians(doubleVal);
		case ULP:
			return Math.ulp(doubleVal);

		default:
			log.warn("RealUnaryExpression: unimplemented operator: " + op);
			return null;
		}

	}

	@Override
	public Object visit(RealVariable n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(StringReaderExpr n, Void arg) {

		String conc_string = (String) n.getString().accept(this, null);
		if (n.getReaderPosition() >= conc_string.length()) {
			return -TRUE_VALUE;
		} else {
			return (long) conc_string.charAt(n.getReaderPosition());
		}
	}

	@Override
	public Object visit(IntegerToStringCast n, Void arg) {
		Long exprVal = (Long) n.getArgument().accept(this, null);
		return Long.toString(exprVal);
	}

	@Override
	public Object visit(RealToStringCast n, Void arg) {
		Double doubleObject = (Double) n.getArgument().accept(this, null);
		return Double.toString(doubleObject);
	}

	@Override
	public Object visit(StringBinaryExpression n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		Object second = (Object) n.getRightOperand().accept(this, null);

		Operator op = n.getOperator();
		switch (op) {

		// returns String
		case CONCAT: {
			String string = (String) second;
			return first.concat(string);
		}
		case APPEND_BOOLEAN: {
			Long sndLong = (Long) second;
			boolean booleabValue = sndLong == 0 ? false : true;
			return first + booleabValue;
		}
		case APPEND_CHAR: {
			Long sndLong = (Long) second;
			char charValue = (char) sndLong.longValue();
			return first + charValue;
		}
		case APPEND_INTEGER: {
			Long sndLong = (Long) second;
			return first + sndLong;
		}
		case APPEND_REAL: {
			Double sndLong = (Double) second;
			return first + sndLong;
		}
		case APPEND_STRING: {
			String string = (String) second;
			return first + (string);
		}

		default:
			log.warn("StringBinaryExpression: unimplemented operator! Operator" + op.toString());
			return null;
		}

	}

	@Override
	public Object visit(StringConstant n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(StringMultipleExpression n, Void arg) {
		String first = (String) n.getLeftOperand().accept(this, null);
		Object right = (Object) n.getRightOperand().accept(this, null);
		ArrayList> other_v = n.getOther();
		long secLong, thrdLong;
		String secStr, thrdStr;

		Operator op = n.getOperator();
		switch (op) {

		// returns string
		case SUBSTRING: {
			secLong = (Long) right;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return first.substring((int) secLong, (int) thrdLong);
		}
		case REPLACEC:
			secLong = (Long) right;
			thrdLong = (Long) other_v.get(0).accept(this, null);
			return first.replace((char) secLong, (char) thrdLong);
		case REPLACECS:
			secStr = (String) right;
			thrdStr = (String) other_v.get(0).accept(this, null);
			return first.replace(secStr, thrdStr);
		case REPLACEALL:
			secStr = (String) right;
			thrdStr = (String) other_v.get(0).accept(this, null);
			return first.replaceAll(secStr, thrdStr);
		case REPLACEFIRST:
			secStr = (String) right;
			thrdStr = (String) other_v.get(0).accept(this, null);
			return first.replaceFirst(secStr, thrdStr);
		default:
			log.warn("StringMultipleExpression: unimplemented operator: " + op);
			return null;
		}

	}

	@Override
	public Object visit(StringUnaryExpression n, Void arg) {
		String exOn = (String) n.getOperand().accept(this, null);

		Operator op = n.getOperator();
		switch (op) {

		case TOLOWERCASE:
			return exOn.toLowerCase();
		case TOUPPERCASE:
			return exOn.toUpperCase();
		case TRIM:
			return exOn.trim();

		default:
			log.warn("StringUnaryExpression: unimplemented operator!" + op);
			return null;
		}
	}

	@Override
	public Object visit(StringVariable n, Void arg) {
		return n.getConcreteValue();
	}

	@Override
	public Object visit(HasMoreTokensExpr n, Void arg) {
		StringTokenizer tokenizer = (StringTokenizer) n.getTokenizerExpr().accept(this, null);
		return tokenizer.hasMoreTokens() ? TRUE_VALUE : FALSE_VALUE;
	}

	@Override
	public Object visit(NewTokenizerExpr n, Void arg) {
		String stringVal = (String) n.getString().accept(this, null);
		String delimVal = (String) n.getDelimiter().accept(this, null);
		StringTokenizer tokenizer = new StringTokenizer(stringVal, delimVal);
		return tokenizer;
	}

	@Override
	public Object visit(NextTokenizerExpr n, Void arg) {
		StringTokenizer tokenizer = (StringTokenizer) n.getTokenizerExpr().accept(this, null);
		tokenizer.nextToken();
		return tokenizer;
	}

	@Override
	public Object visit(StringNextTokenExpr n, Void arg) {
		StringTokenizer tokenizer = (StringTokenizer) n.getTokenizerExpr().accept(this, null);
		return tokenizer.nextToken();
	}

	@Override
	public Object visit(ReferenceConstant r, Void arg) {
		return r.getConcreteValue();
	}

	@Override
	public Object visit(ReferenceVariable r, Void arg) {
		return r.getConcreteValue();
	}

	@Override
	public Object visit(GetFieldExpression r, Void arg) {
		final Object conc_receiver = r.getReceiverExpr().accept(this, arg);
		final String field_name = r.getFieldName();
		if (conc_receiver == null) {
			// TODO
			throw new UnsupportedOperationException("How the null case should be handled?");
		}
		try {
			Field field = conc_receiver.getClass().getField(field_name);
			final boolean isAccessible = field.isAccessible();
			field.setAccessible(true);
			Object ret_value = field.get(conc_receiver);
			field.setAccessible(isAccessible);
			return ret_value;
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy