blob: 8715a882066b5c2507eb614f192f8bf5736f038a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 7 janv. 2014
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmHitOrJumpProcessor.h"
#include "HitOrderedProcessor.h"
#include "HitUnorderedProcessor.h"
#include <collection/Typedef.h>
#include <fml/runtime/ExecutionContext.h>
#include <fam/queue/ExecutionQueue.h>
#include <fml/workflow/Query.h>
#include <fml/workflow/WObject.h>
#include <sew/SymbexControllerRequestManager.h>
namespace sep
{
/*
prototype process::hit_or_jump as &avm::processor.HIT_OR_JUMP is
section REPORT
@uri = std ":" ( "cout" | "cerr" )
| avm ":" ( "log" | "trace" )
| folder ":" path
| file ":" path
| filename ":" path
| socket ":" host ":" port
;
@uri = ...;
@when = [ init ][:][ otf | (every | after | before)?value#unit][:][ exit ] ;
endsection REPORT
section SCHEDULING
@startup = 'waiting';
endsection SCHEDULING
section PROPERTY
// Nombre de pas de calcul "cumulés" avant de débuter la vérification de la couverture
@begin_step = 0;
// Arrète l'exécution dès que la couverture est complète
@stop = true;
// Elagage du graphe des scénarios à la fin de la vérification
@slice = true;
// Active l'utilisation d'heuristique
@heuristic = true;
// Cherche une trace globalement ou locale à chaque noeud racine...
@search#scope = 'GLOBALLY'; // GLOBALLY | LOCALLY ;
// |;| --> ordered (operator: sequence)
// |<| --> ordered (operator: order)
// |i| --> unordered (operator: interleaving)
// |regex| --> regex (operator: regex)
@scheduler = '|<|';
// Hauteur du jump
@jump#height = 4;
// the Jump trials limit exploration property
@jump#limit = 15;
// Choisir des traces avec ou sans trous
@hit#consecutive = false;
// Rechercher un maximum de traces solutions
// Possible backtracking
@hit#max = false;
// Ne faire qu'une tentative vers l'objectif (avoir de la chance!)
// Pas de backtrack
@hit#lucky = true;
// Nombre de chemins positifs sélectionnables ALEATOIREMENT
@hit#count = -1;
// Nombre de chemins négatifs sélectionnables ALEATOIREMENT
@jump#count = 1;
// Effectue une sélection finale (relativement à @hit#count)
// lorsque l'objectif est atteint !
@hit#final = true;
// Slice les hit/jump non retenus aléatoirement
@jump#slice = true;
endsection PROPERTY
// Declaration part
section POINT
@assign = "sens";
@newfresh = "sens";
@signal#sens = "sens";
@port = "env";
@input = "env";
@output = "env";
@output = "Thermostat->dt";
@input = "Thermostat->equip";
@output2 = "Equipment->error";
endsection POINT
section TRACE
@trace = ${ && "signal#sens" "output2" };
@trace = [ "signal#sens" , "output2" ];
@point = ( "signal#sens" || "output2" );
@composite = ${ xor "signal#sens" "output2" };
@assign = "sens";
@newfresh = "sens";
@signal = "sens";
@port = "env";
@input = "env";
@output = "env";
@output = "Thermostat->dt";
@input = "Thermostat->equip";
@output = "Equipment->error";
@transition = "Thermostat->transition#2#MSGm1#in";
@routine = "Thermostat->transition#2#MSGm1#in";
@machine = "Thermostat";
@state = "Thermostat->s4";
@formula = <expression>;
endsection TRACE
endprototype
*/
////////////////////////////////////////////////////////////////////////////////
// CONFIGURE API
////////////////////////////////////////////////////////////////////////////////
bool AvmHitOrJumpProcessor::configureImpl()
{
// SUPER CONFIGURATION
mConfigFlag = BaseCoverageFilter::configureImpl();
WObject * thePROPERTY = Query::getRegexWSequence(getParameterWObject(),
OR_WID2("property", "PROPERTY"), getParameterWObject());
if( thePROPERTY != WObject::_NULL_ )
{
std::string strScheduler = Query::getRegexWPropertyString(
thePROPERTY, CONS_WID2("search", "scope"), "GLOBALLY");
StringTools::toupper( strScheduler );
mGlobalSearchScopeFlag = ( strScheduler == "GLOBALLY" );
strScheduler = Query::getWPropertyString(thePROPERTY, "scheduler", "|;|");
scheduler = OperatorLib::toOpcode(strScheduler, AVM_OPCODE_NULL);
if( scheduler == AVM_OPCODE_NULL )
{
if( strScheduler == "ordered" )
{
scheduler = AVM_OPCODE_SEQUENCE;
}
else if( strScheduler == "unordered" )
{
scheduler = AVM_OPCODE_INTERLEAVING;
}
else if( strScheduler == "regex" )
{
scheduler = AVM_OPCODE_REGEX;
}
}
}
WObject * theHEURISTIC = Query::getRegexWSequence(getParameterWObject(),
OR_WID2("heuristic", "HEURISTIC"), thePROPERTY);
if( theHEURISTIC != WObject::_NULL_ )
{
// the Jump HEIGHT exploration property
long intAttribute = Query::getRegexWPropertyInt(
theHEURISTIC, CONS_WID2("jump", "height"), 7);
if( intAttribute < 0 )
{
mJumpHeight = mJumpDelta = 7;
AVM_IF_DEBUG_FLAG( CONFIGURING )
AVM_OS_LOG << "Invalid jump height ! => replace by "
<< mJumpDelta << " >" << std::endl;
AVM_ENDIF_DEBUG_FLAG( CONFIGURING )
}
else
{
mJumpHeight = mJumpDelta = intAttribute;
}
// the Jump trials limit exploration property
mJumpTrialsLimit = Query::getRegexWPropertyPosSizeT(
theHEURISTIC, CONS_WID3("jump", "(trials", ")?limit"),
AVM_NUMERIC_MAX_SIZE_T, AVM_NUMERIC_MAX_SIZE_T);
// the Hit CONSECUTIVE trace flag property
mHitConsecutiveFlag = Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("hit", "consecutive"), false);
// The Folding Flag when checking Trace Point satisfiability in one EC
mFoldingFlag = Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("hit", "folding"), true);
// the Hitter SELECTION only maximal prefix flag property
mHitMaxFlag = Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("hit", "max"), false);
// Compilation for coherence and optimization
if( mHitMaxFlag )
{
// the Hit LUCKY wish: Only one try, backtracking off
mHitLuckyFlag = false;
// Backtracking enabled !
mBacktrackFlag = true;
// the Hit COUNT selection property
mHitCount = AVM_NUMERIC_MAX_SIZE_T;
}
else
{
// the Hit LUCKY wish: Only one try, backtracking off
mHitLuckyFlag = Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("hit", "lucky"), false);
// Backtracking enabled ?
mBacktrackFlag = (not mHitLuckyFlag);
// the Hit COUNT selection property
mHitCount = Query::getRegexWPropertyPosSizeT(
theHEURISTIC, CONS_WID2("hit", "count"), 1);
}
// the Jump COUNT selection property
mJumpCount = Query::getRegexWPropertyPosSizeT(
theHEURISTIC, CONS_WID2("jump", "count"), 1);
// the Hit FINAL (after objective achieved) flags property mHitFinalFlag
mHitFinalFlag = Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("hit", "final"), true);
// the Jump SLICE (after each hit/jump) flags property
mJumpSliceFlag = (not mBacktrackFlag) &&
Query::getRegexWPropertyBoolean(
theHEURISTIC, CONS_WID2("jump", "slice"), true);
}
else
{
mConfigFlag = false;
}
// the Hit Processor configuration
switch( scheduler )
{
case AVM_OPCODE_INTERLEAVING:
{
mHitProcessor = new HitUnorderedProcessor(*this, ENV);
break;
}
case AVM_OPCODE_SEQUENCE:
case AVM_OPCODE_ATOMIC_SEQUENCE:
case AVM_OPCODE_SEQUENCE_WEAK:
case AVM_OPCODE_PRIOR_GT:
case AVM_OPCODE_NULL:
default:
{
mHitProcessor = new HitOrderedProcessor(*this, ENV);
break;
}
}
if( mHitProcessor->configure(getParameterWObject()) )
{
if( isUnordered() )
{
//mHitCount = AVM_NUMERIC_MAX_SIZE_T;
}
}
else
{
mConfigFlag = false;
}
enablePreprocess( this );
if( mConfigFlag )
{
// Registration to handler DestroyCtx event
getSymbexEventManager().registerHandlerEventDestroyCtx(this);
}
return( mConfigFlag );
}
////////////////////////////////////////////////////////////////////////////////
// REPORT API
////////////////////////////////////////////////////////////////////////////////
void AvmHitOrJumpProcessor::reportMinimum(OutStream & os) const
{
os << TAB << "HIT OR JUMP Coverage "
<< mCoverageStatistics.strCoverageRate(mGoalAchieved) << " ==> "
<< ((mGoalAchieved || mHitProcessor->goalAchieved()) ?
"DONE !" : "FAILED !")
<< std::endl;
if( (not mHitProcessor->goalAchieved()) && (not mGoalAchieved)
&& (mJumpTrialsCount > mJumpTrialsLimit) )
{
os << TAB << ">>> Retry with a greater < jump#limit="
<< mJumpTrialsLimit << " > heuristic attribute ! <<<"
<< std::endl;
}
mHitProcessor->reportMinimum(os);
}
void AvmHitOrJumpProcessor::reportDefault(OutStream & os) const
{
os << TAB << "HIT OR JUMP[ " << mHitProcessor->strKind()
<< " : " << ( mGlobalSearchScopeFlag ? "globally" : "locally" )
<< " ] < heuristic:" << mHeuristicProperty.mHeuristicEnabled
<< " , height:" << mJumpDelta << " , hit:";
((mHitCount < AVM_NUMERIC_MAX_SIZE_T) ? os << mHitCount : os << "<all>")
<< " , jump:";
((mJumpCount < AVM_NUMERIC_MAX_SIZE_T) ? os << mJumpCount : os << "<all>")
<< " ; backtrack:" << mBacktrackFlag << ":"
<< mCoverageStatistics.mNumberOfBacktrack
<< " , black_hole:" << mCoverageStatistics.strBlackHoleRate()
<< " , slice:" << mSliceCount << " >: Coverage "
<< mCoverageStatistics.strCoverageRate(mGoalAchieved) << " ==> "
<< ((mGoalAchieved || mHitProcessor->goalAchieved()) ?
"DONE !" : "FAILED !")
<< std::endl;
if( (not mHitProcessor->goalAchieved()) && (not mGoalAchieved)
&& (mJumpTrialsCount > mJumpTrialsLimit) )
{
os << TAB << ">>> Retry with a greater < jump#limit="
<< mJumpTrialsLimit << " > heuristic attribute ! <<<"
<< std::endl;
}
mHitProcessor->reportDefault(os);
os << TAB << "HIT OR JUMP[ " << mHitProcessor->strKind()
<< " ] < heuristic:" << mHeuristicProperty.mHeuristicEnabled
<< " , height:" << mJumpDelta << " , hit:";
((mHitCount < AVM_NUMERIC_MAX_SIZE_T) ? os << mHitCount : os << "<all>")
<< " , jump:";
((mJumpCount < AVM_NUMERIC_MAX_SIZE_T) ? os << mJumpCount : os << "<all>")
<< " ; backtrack:" << mBacktrackFlag << ":"
<< mCoverageStatistics.mNumberOfBacktrack
<< " , black_hole:" << mCoverageStatistics.strBlackHoleRate()
<< " , slice:" << mSliceCount << " >: Coverage "
<< mCoverageStatistics.strCoverageRate(mGoalAchieved) << " ==> "
<< ((mGoalAchieved || mHitProcessor->goalAchieved()) ?
"DONE !" : "FAILED !")
<< EOL_FLUSH;
}
////////////////////////////////////////////////////////////////////////////////
// NON-REGRESSION TEST API
////////////////////////////////////////////////////////////////////////////////
void AvmHitOrJumpProcessor::tddRegressionReportImpl(OutStream & os)
{
os << TAB << "HIT OR JUMP COVERAGE : "
<< mCoverageStatistics.strCoverageRate() << " ==> "
<< (mHitProcessor->goalAchieved() ? "DONE !" : "FAILED !")
<< EOL_FLUSH;
}
////////////////////////////////////////////////////////////////////////////////
// PROCESS API
////////////////////////////////////////////////////////////////////////////////
//bool AvmHitOrJumpProcessor::preprocess()
//{
// return( true );
//}
//
//
//bool AvmHitOrJumpProcessor::postprocess()
//{
// //BaseCoverageFilter::postprocess();
//
// return( true );
//}
////////////////////////////////////////////////////////////////////////////////
// PRE-FILTER API
////////////////////////////////////////////////////////////////////////////////
bool AvmHitOrJumpProcessor::filteringInitialize()
{
// Preserve every root context
mListOfPositiveEC.append( getExecutionQueue().getInitQueue() );
mInitialRootEC.append( getExecutionQueue().getInitQueue() );
if( mGlobalSearchScopeFlag )
{
mRelativeRootEC.append( getExecutionQueue().getInitQueue() );
}
else if( getExecutionQueue().hasInit() )
{
mBufferLocalRootEC.splice( getExecutionQueue().getInitQueue() );
mRelativeRootEC.append( mBufferLocalRootEC.front() );
// First Jump Height!
mJumpHeight = mJumpDelta + mBufferLocalRootEC.front()->getHeight();
getExecutionQueue().getInitQueue().append( mBufferLocalRootEC.front() );
mBufferLocalRootEC.pop_front();
}
mAbsoluteStopContextFlag = true;
mJumpTrialsCount = 0;
getSymbexRequestManager().postRequestContinue( this );
return( true );
}
bool AvmHitOrJumpProcessor::prefilter()
{
ecQueue = &( getExecutionQueue().getReadyQueue() );
mAbsoluteStopContextFlag = false;
if( ecQueue->nonempty() )
{
ecQueueIt = ecQueue->begin();
ecQueueItEnd = ecQueue->end();
for( ; ecQueueIt != ecQueueItEnd ; )
{
// prefilter(*ecQueueIt);
if( mHitProcessor->goalWillNeverAchieved( *ecQueueIt ) )
{
ecQueueIt = ecQueue->erase( ecQueueIt );
}
else if( (*ecQueueIt)->getHeight() >= mJumpHeight )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< 1 > >>>>> EC< id:"
<< (*ecQueueIt)->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC.append( *ecQueueIt );
ecQueueIt = ecQueue->erase( ecQueueIt );
}
else
{
++ecQueueIt;
}
}
}
return( getExecutionQueue().hasReady() );
}
bool AvmHitOrJumpProcessor::prefilter(ExecutionContext & anEC)
{
if( mHitProcessor->goalAchieved() && mStopFlag )
{
return( false );
}
return( true );
}
/**
* PROCESSOR REQUEST API :> CONITNUE
* Jump step
*/
void AvmHitOrJumpProcessor::handleRequestContinue()
{
if( mRelativeRootEC.empty() )
{
if( not hojBacktrack() )
{
getSymbexRequestManager().postRequestGoalAchieved( this );
}
return;
}
if( mHitProcessor->hit(mJumpHeight) )
{
mSelectionCount = mHitCount;
mHitCaseFlag = true;
if( mHitProcessor->goalAchieved() )
{
mGoalAchieved = true;
if( mHitFinalFlag || mHitMaxFlag )
{
hojSelectionFinal();
}
if( mHitMaxFlag && hojBacktrack() )
{
return;
}
getSymbexRequestManager().postRequestGoalAchieved( this );
if( mStopFlag )
{
return;
}
}
}
else if( mHitConsecutiveFlag && (mCoverageStatistics.mNumberOfCovered > 0) )
{
getSymbexRequestManager().postRequestGoalAchieved( this );
return;
}
else
{
mSelectionCount = mJumpCount;
mHitCaseFlag = false;
}
if( mRelativeLeafEC.nonempty() )
{
hojSelection();
}
else
{
// Locally slice if mJumpSliceFlag
jumpSlice();
if( mBacktrackFlag && hojBacktrack() )
{
return;
}
mAbsoluteStopContextFlag = true;
mRelativeRootEC.clear();
}
if( ++mJumpTrialsCount > mJumpTrialsLimit )
{
getSymbexRequestManager().postRequestGoalAchieved( this );
return;
}
else if( mAbsoluteStopContextFlag )
{
mCoverageStatistics.copyIfBestCoverageRate(mFinalCoverageStatistics);
getSymbexRequestManager().postRequestGoalAchieved( this );
}
else if( mRelativeRootEC.nonempty() )
{
getSymbexRequestManager().postRequestContinue( this );
getExecutionQueue().appendReady( mRelativeRootEC );
mJumpHeight = mJumpHeight + mJumpDelta;
mAbsoluteStopContextFlag = true;
}
else if( not hojBacktrack() )
{
getSymbexRequestManager().postRequestGoalAchieved( this );
}
}
/**
* PROCESSOR REQUEST API :> GOAL_ACHIEVED
* Ending (positive or negative) locally or globally objective
*/
void AvmHitOrJumpProcessor::handleRequestGoalAchieved()
{
if( mGlobalSearchScopeFlag || mBufferLocalRootEC.empty() )
{
// mGoalAchieved = true;
getSymbexRequestManager().postRequestStop( this );
}
else
{
getExecutionQueue().handleRequestStop();
mRelativeRootEC.clear();
mRelativeRootEC.append( mBufferLocalRootEC.front() );
// Reinitialize parameters for restarting;
mJumpHeight = mJumpDelta + mBufferLocalRootEC.front()->getHeight();
mHitProcessor->resetConfig();
mCoverageStatistics.resetCoverageCounter();
getExecutionQueue().pushWaiting( mBufferLocalRootEC.front() );
mBufferLocalRootEC.pop_front();
mAbsoluteStopContextFlag = true;
mJumpTrialsCount = 0;
getSymbexRequestManager().postRequestContinue( this );
}
}
bool AvmHitOrJumpProcessor::hojBacktrack()
{
if( mBacktrackHitEC.empty() )
{
return( false );
}
mFinalCoverageStatistics.copyIfBestCoverageRate( mCoverageStatistics );
++( mFinalCoverageStatistics.mNumberOfBacktrack );
++( mCoverageStatistics.mNumberOfBacktrack );
mBacktrackHitEC.pop_last_to( tmpEC );
getExecutionQueue().pushWaiting( tmpEC );
mCoverageStatistics = tmpEC->getUniqInformation()->
getUniqHitOrJumpObjectiveInfo()->
getCoverageStatistics();
mJumpHeight = tmpEC->getHeight() + mJumpDelta;
mRelativeRootEC.clear();
mRelativeRootEC.append( tmpEC );
mAbsoluteStopContextFlag = true;
getSymbexRequestManager().postRequestContinue( this );
AVM_IF_DEBUG_LEVEL_GTE_MEDIUM
AVM_OS_COUT << "<<<<< HoJ Backtrack EC< id:"
<< tmpEC->getIdNumber() << " > where "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
AVM_OS_TRACE << "<<<<< HoJ Backtrack EC< id:"
<< tmpEC->getIdNumber() << " > where "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_GTE_MEDIUM
return( true );
}
void AvmHitOrJumpProcessor::hojSelection()
{
AVM_IF_DEBUG_LEVEL_GTE_MEDIUM
AVM_OS_COUT << "<<<<< HoJ Coverage : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
AVM_OS_TRACE << "<<<<< HoJ Coverage : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
//!! current Relative Root& Leaf EC
ExecutionContext::traceMinimum(AVM_OS_TRACE,
mRelativeRootEC, "the Relative Root EC");
ExecutionContext::traceMinimum(AVM_OS_TRACE,
mRelativeLeafEC, "the Relative Leaf EC");
AVM_ENDIF_DEBUG_LEVEL_GTE_MEDIUM
// Remove EC when Parent is in any BlackList
updateRelativeLeaf();
// Hit or JUMP
mRelativeRootEC.clear();
leafCount = mRelativeLeafEC.size();
if( leafCount == 0 )
{
// Locally slice if mJumpSliceFlag
jumpSlice();
return;
}
randomMax = leafCount - 1;
if( (mSelectionCount == 1) || (leafCount == 1) )
{
jumpOffset = (leafCount == 1) ? 0 : RANDOM::gen_uint(0, randomMax);
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< 0 > >>>>> EC< id:"
<< mRelativeLeafEC[jumpOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( mHitCaseFlag )
{
mHitProcessor->hitSelect( jumpOffset );
}
else if( mBacktrackFlag )
{
mBacktrackHitEC.remove( mRelativeLeafEC[jumpOffset] );
}
mRelativeRootEC.append( mRelativeLeafEC[jumpOffset] );
}
else if( mSelectionCount < leafCount )
{
jumpOffsetBitset.reset();
jumpOffsetBitset.resize(leafCount, false);
for( leafOffset = 0 ; leafOffset < mSelectionCount ; ++leafOffset )
{
do
{
jumpOffset = RANDOM::gen_uint(0, randomMax);
}
while( jumpOffsetBitset[jumpOffset] );
jumpOffsetBitset[jumpOffset] = true;
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< 0 > >>>>> EC< id:"
<< mRelativeLeafEC[jumpOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( mHitCaseFlag )
{
mHitProcessor->hitSelect( jumpOffset );
}
else if( mBacktrackFlag )
{
mBacktrackHitEC.remove( mRelativeLeafEC[jumpOffset] );
}
mRelativeRootEC.append( mRelativeLeafEC[jumpOffset] );
}
}
else
{
for( leafOffset = 0 ; leafOffset < leafCount ; ++leafOffset )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< 0 > >>>>> EC< id:"
<< mRelativeLeafEC[leafOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( mHitCaseFlag )
{
mHitProcessor->hitSelect( leafOffset );
}
else if( mBacktrackFlag )
{
mBacktrackHitEC.remove( mRelativeLeafEC[jumpOffset] );
}
mRelativeRootEC.append( mRelativeLeafEC[leafOffset] );
}
}
mRelativeLeafEC.clear();
// Locally slice if mJumpSliceFlag
jumpSlice();
AVM_IF_DEBUG_LEVEL_GTE_MEDIUM
AVM_OS_TRACE << "<<<<< HoJ Coverage : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
//!! Next Relative Root EC
ExecutionContext::traceMinimum(AVM_OS_TRACE,
mRelativeRootEC, "the Relative Root EC");
AVM_ENDIF_DEBUG_LEVEL_GTE_MEDIUM
}
void AvmHitOrJumpProcessor::hojSelectionFinal()
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_COUT << "<<<<< HoJ Goal Achieved : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
AVM_OS_TRACE << "<<<<< HoJ Goal Achieved : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
ExecutionContext::traceMinimum(AVM_OS_TRACE,
mRelativeLeafEC, "the Relative Leaf EC");
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
// Hit Final
mRelativeRootEC.clear();
if( mHitMaxFlag )
{
mSelectionCount = mRelativeLeafEC.size();
}
leafCount = mRelativeLeafEC.size();
randomMax = leafCount - 1;
if( (mSelectionCount == 1) || (leafCount == 1) )
{
jumpOffset = (leafCount == 1) ? 0 : RANDOM::gen_uint(0, randomMax);
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< goal achieved > >>>>> EC< id:"
<< mRelativeLeafEC[jumpOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC[jumpOffset]->getwFlags().setObjectiveAchievedTrace();
mListOfPositiveEC.append( mRelativeLeafEC[jumpOffset] );
}
else if( mSelectionCount < leafCount )
{
jumpOffsetBitset.reset();
jumpOffsetBitset.resize(leafCount, false);
for( leafOffset = 0 ; leafOffset < mSelectionCount ; ++leafOffset )
{
do
{
jumpOffset = RANDOM::gen_uint(0, randomMax);
}
while( jumpOffsetBitset[jumpOffset] );
jumpOffsetBitset[jumpOffset] = true;
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< goal achieved > >>>>> EC< id:"
<< mRelativeLeafEC[jumpOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC[jumpOffset]->getwFlags().setObjectiveAchievedTrace();
mListOfPositiveEC.append( mRelativeLeafEC[jumpOffset] );
}
}
else
{
for( leafOffset = 0 ; leafOffset < leafCount ; ++leafOffset )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jump< goal achieved > >>>>> EC< id:"
<< mRelativeLeafEC[leafOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC[jumpOffset]->getwFlags().setObjectiveAchievedTrace();
mListOfPositiveEC.append( mRelativeLeafEC[leafOffset] );
}
}
mRelativeLeafEC.clear();
// Locally slice if mJumpSliceFlag
jumpSlice();
AVM_IF_DEBUG_LEVEL_GTE_MEDIUM
AVM_OS_TRACE << "<<<<< HoJ Coverage : "
<< mCoverageStatistics.strCoverageRate() << " >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_GTE_MEDIUM
}
void AvmHitOrJumpProcessor::updateRelativeLeaf()
{
jumpOffset = 0;
leafCount = mRelativeLeafEC.size();
// Position for Left Shift of non-BlackListed Context Leaf
randomMax = leafCount;
// Mark Blacklisted Context Leaf using NULL
for( leafOffset = 0 ; leafOffset < leafCount ; ++leafOffset )
{
tmpEC = mRelativeLeafEC[leafOffset];
if( mAbsoluteLeafEC.contains( tmpEC ) )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< hoj< leaf failed > >>>>> EC< id:"
<< mRelativeLeafEC[leafOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC[leafOffset] = NULL;
if( randomMax == leafCount )
{
randomMax = leafOffset;
}
continue;
}
for( jumpOffset = 0 ; jumpOffset < mJumpDelta ; ++jumpOffset )
{
if( tmpEC->isRoot() || mInitialRootEC.contains(tmpEC) )
{
break;
}
else if( mBlackHoleEC.contains( tmpEC ) )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< hoj< leaf failed > >>>>> EC< id:"
<< mRelativeLeafEC[leafOffset]->getIdNumber() << " >" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mRelativeLeafEC[leafOffset] = NULL;
if( randomMax == leafCount )
{
randomMax = leafOffset;
}
break;
}
tmpEC = tmpEC->getPrevious();
}
if( (randomMax < leafCount) && (mRelativeLeafEC[leafOffset] != NULL) )
{
mRelativeLeafEC[randomMax++] = mRelativeLeafEC[leafOffset];
}
}
// Remove NULL Context Leaf
if( randomMax < leafCount )
{
mRelativeLeafEC.resize( randomMax );
}
}
/**
* Slice leaf in mSliceableEC
* w.r.t. the hit/jump/preserved leaf in mRelativeRootEC/mPreservedEC
* and backward until mJumpDelta
*/
void AvmHitOrJumpProcessor::jumpSlice()
{
// //!! Blacktrack
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mBacktrackHitEC, "the Backtrack Hit EC");
//
// //!! BlackHole ?
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mBlackHoleEC, "the Black Hole EC");
//
// //!! DeadLock or Absolute Stop ?
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mAbsoluteLeafEC, "the Absolute Leaf EC");
if( mJumpSliceFlag )
{
if( mHitLuckyFlag )
{
mBlackHoleEC.clear();
mAbsoluteLeafEC.clear();
jumpSliceLucky();
}
else // if( mBacktrackFlag )
{
jumpSliceBacktrack();
}
AVM_IF_DEBUG_LEVEL_GTE_MEDIUM
AVM_OS_TRACE << "<<<<< Slice count : " << mSliceCount
<< " >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_GTE_MEDIUM
}
mSliceableEC.clear();
}
void AvmHitOrJumpProcessor::updatePreserved()
{
mJumpPreservedEC.clear();
mJumpPreservedLeavesEC.clear();
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mRelativeRootEC, "the Relative Root EC");
mJumpPreservedLeavesEC.append(mRelativeRootEC);
ecItEnd = mJumpPreservedLeavesEC.end();
for( ecIt = mJumpPreservedLeavesEC.begin() ; ecIt != ecItEnd ; ++ecIt )
{
tmpEC = (*ecIt);
mJumpPreservedEC.append( tmpEC );
if( tmpEC->isRoot() || mInitialRootEC.contains(tmpEC) )
{
continue;
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< preserved EC< id: "
<< tmpEC->getIdNumber() << " > >>>>> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
for( jumpOffset = 1 ; jumpOffset < mJumpDelta ; ++jumpOffset )
{
tmpEC = tmpEC->getPrevious();
if( tmpEC->isRoot() || mInitialRootEC.contains(tmpEC) ||
mJumpPreservedEC.contains( tmpEC ) )
{
continue;
}
mJumpPreservedEC.append( tmpEC );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< preserved EC< id: "
<< tmpEC->getIdNumber() << " > >>>>> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
}
}
void AvmHitOrJumpProcessor::jumpSliceLucky()
{
updatePreserved();
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mJumpPreservedEC, "the Jump Preserved EC");
//
// ExecutionContext::traceMinimum(AVM_OS_TRACE,
// mJumpPreservedLeavesEC, "the Jump Preserved Leaves EC");
ecItEnd = mJumpPreservedLeavesEC.end();
for( ecIt = mJumpPreservedLeavesEC.begin() ; ecIt != ecItEnd ; ++ecIt )
{
tmpEC = (*ecIt);
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice from preserved leaf EC< id: "
<< tmpEC->getIdNumber() << " > >>>>> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( tmpEC->isRoot() || mInitialRootEC.contains(tmpEC) )
{
continue;
}
for( jumpOffset = 0 ; jumpOffset < mJumpDelta ; ++jumpOffset )
{
tmpEC = tmpEC->getPrevious();
if( tmpEC->isRoot() || mInitialRootEC.contains(tmpEC) )
{
break;
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice from preserved EC< id: "
<< tmpEC->getIdNumber() << " > >>>>> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
endChildEC = tmpEC->end();
for( itChildEC = tmpEC->begin() ; itChildEC != endChildEC ; )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice ??? EC< id: " << (*itChildEC)->getIdNumber()
<< " > >>>>> count:> " << mSliceCount << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( mJumpPreservedEC.contains( *itChildEC ) )
{
++itChildEC;
}
else
{
prevEC = (*itChildEC);
itChildEC = tmpEC->eraseChildContext( itChildEC );
prevEC->setContainer( NULL );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice EC< id: " << prevEC->getIdNumber()
<< " > >>>>> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mSliceCount = mSliceCount + AbstractProcessorUnit::remove(
prevEC, AVM_OS_TRACE, "<<<<< jumpSliceLucky" );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice count: " << mSliceCount
<< " >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
}
}
}
}
void AvmHitOrJumpProcessor::jumpSliceBacktrack()
{
//!! BlackHole ?
mSliceableEC.splice( mBlackHoleEC );
//!! DeadLock or Absolute Stop ?
mSliceableEC.splice( mAbsoluteLeafEC );
// mSliceableEC.unique();
ecItEnd = mSliceableEC.end();
for( ecIt = mSliceableEC.begin() ; ecIt != ecItEnd ; ++ecIt )
{
tmpEC = (*ecIt);
for( jumpOffset = 0 ; jumpOffset <= mJumpDelta ; ++jumpOffset )
{
if( (tmpEC->hasNext() && (jumpOffset > 0)) || tmpEC->isRoot() ||
mListOfPositiveEC.contains(tmpEC) )
{
break;
}
prevEC = tmpEC->getPrevious();
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice EC< id: " << tmpEC->getIdNumber()
<< " > >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
mSliceCount = mSliceCount + AbstractProcessorUnit::remove(
tmpEC, AVM_OS_TRACE, "<<<<< jumpSliceBacktrack" );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_TRACE << "<<<<< jumpSlice count: " << mSliceCount
<< " >>>>>" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
tmpEC = prevEC;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// POST-FILTER API
////////////////////////////////////////////////////////////////////////////////
bool AvmHitOrJumpProcessor::postfilter()
{
// ecQueue = &( getExecutionQueue().getResultQueue() );
// ecQueueItEnd = ecQueue->end();
// for( ecQueueIt = ecQueue->begin() ; ecQueueIt != ecQueueItEnd ; )
// {
// if( postfilter(*ecQueueIt) )
// {
// ++ecQueueIt;
// }
// else
// {
// ecQueueIt = ecQueue->erase(ecQueueIt);
// }
// }
return( getExecutionQueue().hasResult() );
}
bool AvmHitOrJumpProcessor::postfilter(ExecutionContext & anEC)
{
// if( mHitProcessor->hit(anEC) )
// {
// if( mHitProcessor->goalAchieved() && mStopFlag )
// {
// return( false );
// }
// }
return( true );
}
/**
* IHandlerEventDestroyCtx API
* Destroy Execution Context
*/
void AvmHitOrJumpProcessor::handleEventDestroyCtx(ExecutionContext * anEC)
{
mBacktrackHitEC.remove( anEC );
}
////////////////////////////////////////////////////////////////////////////
// FINAL SLICING TOOLS
////////////////////////////////////////////////////////////////////////////
bool AvmHitOrJumpProcessor::isSliceableContext(ExecutionContext & anEC) const
{
if( mHitProcessor->goalAchieved() )
{
return( anEC.getFlags().noneObjectiveAchievedTrace()
&& (not mInitialRootEC.contains(& anEC)) );
}
else
{
return( anEC.getFlags().noneCoverageElementTrace()
&& (not mInitialRootEC.contains(& anEC))
&& (not mListOfPositiveEC.contains(& anEC)) );
}
}
} /* namespace sep */