Example #1
0
  /** {@inheritDoc} */
  @Override
  public void afterStatement(Statement statement, Scope scope, Throwable exception) {
    try {
      for (VariableReference var : statement.getVariableReferences()) {
        if (var.equals(statement.getReturnValue())
            || var.equals(statement.getReturnValue().getAdditionalVariableReference())) continue;
        Object object = var.getObject(scope);

        if (var.isPrimitive()) {
          ConstantValue value = new ConstantValue(test, var.getGenericClass());
          value.setValue(object);
          // logger.info("Statement before inlining: " + statement.getCode());
          statement.replace(var, value);
          // logger.info("Statement after inlining: " + statement.getCode());
        } else if (var.isString() && object != null) {
          ConstantValue value = new ConstantValue(test, var.getGenericClass());
          try {
            String val = StringEscapeUtils.unescapeJava(object.toString());
            value.setValue(val);
            statement.replace(var, value);
          } catch (IllegalArgumentException e) {
            // Exceptions may happen if strings are not valid unicode
            logger.info("Cannot escape invalid string: " + object);
          }
          // logger.info("Statement after inlining: " + statement.getCode());
        } else if (var.isArrayIndex()) {
          // If this is an array index and there is an object outside the array
          // then replace the array index with that object
          for (VariableReference otherVar : scope.getElements(var.getType())) {
            Object otherObject = otherVar.getObject(scope);
            if (otherObject == object
                && !otherVar.isArrayIndex()
                && otherVar.getStPosition() < statement.getPosition()) {
              statement.replace(var, otherVar);
              break;
            }
          }
        } else {
          // TODO: Ignoring exceptions during getObject, but keeping the assertion for now
          if (object == null) {
            ConstantValue value = new ConstantValue(test, var.getGenericClass());
            value.setValue(null);
            // logger.info("Statement before inlining: " + statement.getCode());
            statement.replace(var, value);
            // logger.info("Statement after inlining: " + statement.getCode());
          }
        }
      }
    } catch (CodeUnderTestException e) {
      logger.warn("Not inlining test: " + e.getCause());
      // throw new AssertionError("This case isn't handled yet: " + e.getCause()
      //        + ", " + Arrays.asList(e.getStackTrace()));
    }
  }
Example #2
0
  /**
   * Remove all unreferenced variables
   *
   * @param t The test case
   * @return True if something was deleted
   */
  public boolean removeUnusedVariables(TestCase t) {
    List<Integer> toDelete = new ArrayList<Integer>();
    boolean hasDeleted = false;

    int num = 0;
    for (Statement s : t) {
      if (s instanceof PrimitiveStatement) {

        VariableReference var = s.getReturnValue();
        if (!t.hasReferences(var)) {
          toDelete.add(num);
          hasDeleted = true;
        }
      }
      num++;
    }
    Collections.sort(toDelete, Collections.reverseOrder());
    for (Integer position : toDelete) {
      t.remove(position);
    }

    return hasDeleted;
  }
  private void minimizeAssertions(
      StructuredTestCase test,
      ExecutionResult origResult,
      Map<Mutation, ExecutionResult> mutationResults) {
    Set<Integer> killedMutants = new HashSet<Integer>();

    for (int position = test.size() - 1; position >= test.getFirstExerciseStatement(); position--) {
      Statement statement = test.getStatement(position);
      if (!statement.hasAssertions()) continue;

      List<Assertion> assertions = new ArrayList<Assertion>(statement.getAssertions());
      Map<Integer, Set<Integer>> killMap = getKillMap(assertions, mutationResults);
      int num = 0;

      // This is to make sure we prefer assertions on return values.
      // TODO: Refactor
      for (Assertion assertion : assertions) {
        if (assertion instanceof PrimitiveAssertion) {
          boolean killsNew = false;
          for (Integer mutationId : killMap.get(num)) {
            if (!killedMutants.contains(mutationId)) {
              killsNew = true;
              break;
            }
          }
          if (!killsNew) {
            statement.removeAssertion(assertion);
          } else {
            killedMutants.addAll(killMap.get(num));
          }
        }
        num++;
      }

      for (int i = 0; i < assertions.size(); i++) {
        if (!killMap.containsKey(i)) {
          statement.removeAssertion(assertions.get(i));
          continue;
        }
        Assertion assertion = assertions.get(i);
        boolean killsNew = false;
        for (Integer mutationId : killMap.get(i)) {
          if (!killedMutants.contains(mutationId)) {
            killsNew = true;
            break;
          }
        }
        if (!killsNew) {
          statement.removeAssertion(assertion);
        } else {
          killedMutants.addAll(killMap.get(i));
        }
      }

      // If we have no assertions, then add...something?
      if (!statement.hasAssertions()) {
        boolean addedPrimitive = false;
        for (Assertion assertion : assertions) {
          if (assertion instanceof PrimitiveAssertion) {
            statement.addAssertion(assertion);
            addedPrimitive = true;
          }
        }
        if (!addedPrimitive) statement.addAssertion(Randomness.choice(assertions));
      }
    }
  }
  @Override
  public boolean doSearch(
      TestChromosome individual, LocalSearchObjective<TestChromosome> objective) {

    logger.info("Test before local search: " + individual.getTestCase().toCode());

    boolean improved = false;

    // Only apply local search up to the point where an exception was thrown
    // TODO: Check whether this conflicts with test expansion
    int lastPosition = individual.size() - 1;
    if (individual.getLastExecutionResult() != null && !individual.isChanged()) {
      Integer lastPos = individual.getLastExecutionResult().getFirstPositionOfThrownException();
      if (lastPos != null) lastPosition = lastPos.intValue();
    }
    TestCase test = individual.getTestCase();

    // We count down to make the code work when lines are
    // added during the search (see NullReferenceSearch).

    for (int i = lastPosition; i >= 0; i--) {
      if (LocalSearchBudget.getInstance().isFinished()) break;

      if (objective.isDone()) {
        break;
      }

      if (i >= individual.size()) {
        logger.warn("Test size decreased unexpectedly during local search, aborting local search");
        logger.warn(individual.getTestCase().toCode());
        break;
      }
      final Class<?> targetClass = Properties.getTargetClassAndDontInitialise();

      final Statement statement = test.getStatement(i);

      if (!test.hasReferences(statement.getReturnValue())
          && !statement.getReturnClass().equals(targetClass)) {
        logger.info(
            "Return value of statement "
                + i
                + " is not referenced and not SUT, not doing local search");
        continue;
      }

      StatementLocalSearch search = StatementLocalSearch.getLocalSearchFor(statement);
      if (search != null) {
        logger.info(
            "Applying local search of type "
                + search.getClass()
                + " to statement "
                + statement
                + " / "
                + individual.getTestCase().getStatement(i));
        if (search.doSearch(individual, i, (LocalSearchObjective<TestChromosome>) objective)) {
          improved = true;
        }
        // i = s.getPosition();
        logger.debug(
            "Old position was: " + i + ", adjusting to: " + (i + search.getPositionDelta()));
        i += search.getPositionDelta();
        test = individual.getTestCase();
      } else {
        /*
         * No statement local search has been produced for this
         * statement. Skipping.
         */
        continue;
      }
    }

    LocalSearchBudget.getInstance().countLocalSearchOnTest();

    // logger.warn("Test after local search: " +
    // individual.getTestCase().toCode());

    // Return true iif search was successful
    return improved;

    // TODO: Handle arrays in local search
    // TODO: mutating an int might have an effect on array lengths
  }