/**
   * Add all assertions to the test case
   *
   * @param test
   * @param origResult
   * @param mutantResult
   * @return
   */
  private int addAssertions(
      StructuredTestCase test,
      ExecutionResult origResult,
      Map<Mutation, ExecutionResult> mutationResults) {
    int numKilled = 0;

    for (Class<?> observerClass : observerClasses) {
      if (origResult.getTrace(observerClass) == null) continue;

      for (int i = 0; i < test.size(); i++) {
        if (test.isExerciseStatement(i))
          origResult.getTrace(observerClass).getAllAssertions(test, i);
      }
    }

    minimizeAssertions(test, origResult, mutationResults);

    return numKilled;
  }
  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));
      }
    }
  }