Пример #1
0
list<pair<const EState*, int> > CounterexampleAnalyzer::removeTraceLeadingToErrorState(const EState* errorState, TransitionGraph* stg) {
  assert(errorState->io.isFailedAssertIO() || errorState->io.isStdErrIO() );
  list<pair<const EState*, int> > erroneousTransitions;
  PState* pstate = const_cast<PState*>( errorState->pstate() ); 
  int latestInputVal = (*pstate)[_analyzer->globalVarIdByName("input")].getValue().getIntValue();
  //eliminate the error state
  const EState* eliminateThisOne = errorState;
  EStatePtrSet preds = stg->pred(eliminateThisOne);
  assert (stg->succ(eliminateThisOne).size() == 0); // error state should have no successors.
  assert (preds.size() == 1); // error states are immediately removed after being discovered.
  const EState* currentState = *(preds.begin());
  stg->eliminateEState(eliminateThisOne);
  //in the case of new input->output->error behavior, delete the output too
  if (currentState->io.isStdOutIO()) {
    eliminateThisOne = currentState;
    preds = stg->pred(currentState);
    assert (preds.size() == 1);
    currentState = *(preds.begin());
    stg->eliminateEState(eliminateThisOne);
  }
  //also delete the input state right before
  assert (currentState->io.isStdInIO());
  eliminateThisOne = currentState;
  preds = stg->pred(currentState);
  // exclude all edges leading to the input state right before the error state for future tracing attempts
  // (due to the reduction to observable behavior, even a single execution trace can lead to multiple predecessors)
  for (EStatePtrSet::iterator i=preds.begin(); i!= preds.end(); ++i) {
    erroneousTransitions.push_back(pair<const EState*, int>(*i, latestInputVal));
  }
  stg->eliminateEState(eliminateThisOne);
  return erroneousTransitions;
}
Пример #2
0
CEAnalysisStep CounterexampleAnalyzer::getSpuriousTransition(list<CeIoVal> partOfCeTrace, TransitionGraph* originalTraceGraph, 
                                           const EState* compareFollowingHere, StateSets* statesPerCycleIndex) {
  assert(compareFollowingHere);
  const EState* currentState = compareFollowingHere;
  bool matchingState;
  CeIoVal realBehavior;
  int index = 1;
  CEAnalysisStep result;
  result.assertionCausingSpuriousInput = false;
  StateSets::iterator cycleIndexStates;
  if (statesPerCycleIndex) { //bookkeeping for analyzing the cyclic part of the counterexample
    cycleIndexStates = statesPerCycleIndex->begin();
  }
  // iterate over part of the counterexample and compare its behavior step-by-step against the original program's trace
  for (list<CeIoVal>::iterator i = partOfCeTrace.begin(); i != partOfCeTrace.end(); i++) {
    matchingState = false;
    EStatePtrSet successors = originalTraceGraph->succ(currentState);
    // the trace graph should always contain enough states for the comparision
    assert(successors.size()>0);
    // retrieve the correct state at branches in the original program (branches may exist due to inherent loops)
    // note: assuming deterministic input/output programs
    for (EStatePtrSet::iterator succ = successors.begin(); succ != successors.end(); succ++) {
      realBehavior = eStateToCeIoVal(*succ);
      //cout << "DEBUG: realBehavior: " << ceIoValToString(realBehavior) << "   ceTraceItem: " << ceIoValToString(*i) << endl;
      if (realBehavior == (*i)) {  //no spurious behavior when following this path, so continue here
        currentState = (*succ);
        index++;
        matchingState = true;
        if (statesPerCycleIndex) {
          //check if the real state has already been seen
          pair<boost::unordered_set<const EState*>::iterator, bool> notYetSeen = cycleIndexStates->insert(currentState);
          if (notYetSeen.second == false) {
            //state encountered twice at the some counterexample index. cycle found --> real counterexample
            result.analysisResult = CE_TYPE_REAL;
            return result;
          } else {
            cycleIndexStates++;
          }
        }
      // special case. output-> failing assertion occurs during execution of the original program, leading to a spurious input symbol.
      // RefinementConstraints should use the failing assertion's condition to add new constraints, trying to enforce the assertion to fail
      // and thus eliminating the spurious input symbol.
      } else if (realBehavior.second == IO_TYPE_ERROR && i->second == IO_TYPE_INPUT) {
        result.assertionCausingSpuriousInput = true;
        result.failingAssertionInOriginal = (*succ)->label();
      }
    }
    // if no matching transition was found, then the counterexample trace is spurious
    if (!matchingState) {
      result.analysisResult = CE_TYPE_SPURIOUS;
      result.spuriousIndexInCurrentPart = index;
      return result;
    }
  }
  IoType mostRecentOriginalIoType = (partOfCeTrace.rbegin())->second;
  determineAnalysisStepResult(result, mostRecentOriginalIoType, currentState, originalTraceGraph, index);
  return result; // partOfCeTrace could be successfully traversed on the originalTraceGraph
}
Пример #3
0
void CounterexampleAnalyzer::determineAnalysisStepResult(CEAnalysisStep& result, IoType mostRecentOriginalIoType, 
                                                const EState* currentState, TransitionGraph* originalTraceGraph, int index) {
  result.analysisResult = CE_TYPE_UNKNOWN;
  result.mostRecentStateRealTrace = currentState;
  result.continueTracingOriginal = true;
  // set and return the result
  //  Takes care of the corner case that error states after the lastly assessed input symbol render
  //  further tracing of the original program's path impossible.
  if (mostRecentOriginalIoType == IO_TYPE_INPUT) {
    EStatePtrSet successors = originalTraceGraph->succ(currentState);
    assert(successors.size() == 1);  //(input-)determinism of the original program
    const EState * nextEState = *(successors.begin());
    assert(nextEState);
    if (nextEState->io.isStdErrIO() || nextEState->io.isFailedAssertIO()) {
      // (*) see below (the first symbol of the next partOfCeTrace has to be the spurious transition here)
      result.analysisResult = CE_TYPE_SPURIOUS;
      result.spuriousIndexInCurrentPart = index;
    } else if (nextEState->io.isStdOutIO()) {
      successors = originalTraceGraph->succ(nextEState);
      for (EStatePtrSet::iterator i = successors.begin(); i != successors.end(); ++i) {
        const EState* nextEState = *i;
        if (nextEState->io.isStdErrIO() || nextEState->io.isFailedAssertIO()) {
          // (*) see below
          result.continueTracingOriginal = false;
        }
      }
    }
  } else if (mostRecentOriginalIoType == IO_TYPE_OUTPUT) {
    EStatePtrSet successors = originalTraceGraph->succ(currentState);
    for (EStatePtrSet::iterator i = successors.begin(); i != successors.end(); ++i) {
      const EState* nextEState = *i;
      if (nextEState->io.isStdErrIO() || nextEState->io.isFailedAssertIO()) {
        // (*) see below
        result.continueTracingOriginal = false;
      }
    }
  }
  // (*) there is a not yet seen error state. Because every state except from successors of the last input state of the trace have
  //     been looked at already, the cycle part of the CE contains no input state before the error state. RERS programs need to
  //     contain at least one input symbol in the cycle part of a counterexample --> this counterexample is spurious.
}