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

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

/**
 * 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 ExpressionEvaluator implements ExpressionVisitor {

  private static final long TRUE_VALUE = 1L;
  private static final long FALSE_VALUE = 0L;
  protected static final Logger log = LoggerFactory.getLogger(ExpressionEvaluator.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 STARTSWITH:
        return first.startsWith(second) ? TRUE_VALUE : FALSE_VALUE;
      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