blob: 1015fca20d01f45a7a5a58fdf0c03b716a2a3705 [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: fev. 2012
*
* Contributors:
* Jose Escobedo (CEA LIST) jose.escobedo@cea.fr
* Mathilde Arnaud (CEA LIST) mathilde.arnaud@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "OfflineTestProcessor.h"
#include <algorithm>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iterator>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <util/avm_util.h>
#include <util/avm_vfs.h>
#include <builder/Builder.h>
#include <computer/primitive/AvmCommunicationFactory.h>
#include <computer/PathConditionProcessor.h>
#include <collection/Typedef.h>
#include <fml/numeric/Float.h>
#include <fml/numeric/Number.h>
#include <fml/expression/ExpressionConstant.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/executable/ExecutableQuery.h>
#include <fml/executable/InstanceOfData.h>
#include <fml/infrastructure/ComProtocol.h>
#include <fml/runtime/ExecutionConfiguration.h>
#include <fml/runtime/ExecutionContext.h>
#include <fml/runtime/ExecutionInformation.h>
#include <fml/runtime/RuntimeQuery.h>
#include <fml/template/TimedMachine.h>
#include <fml/trace/TraceFactory.h>
#include <fam/api/ProcessorUnitRepository.h>
#include <fam/queue/ExecutionQueue.h>
#include <fml/workflow/Query.h>
#include <fml/workflow/WObject.h>
#include <sew/Configuration.h>
#include <solver/api/SolverFactory.h>
namespace sep
{
/**
* CONSTRUCTOR
* Default
*/
OfflineTestProcessor::OfflineTestProcessor(
SymbexControllerUnitManager & aControllerUnitManager,
WObject * wfParameterObject)
: RegisteredProcessorUnit(aControllerUnitManager , wfParameterObject,
AVM_PREPOST_FILTERING_STAGE | AVM_POST_PROCESSING_STAGE,
PRECEDENCE_OF_TEST_OFFLINE),
INFO_OFFLINETEST_DATA( new Identifier( "OFFLINE_TEST" ) ),
INFO_OFFLINETEST_DATA_PASS( new Identifier( "OFFLINE_TEST_PASS" ) ),
INFO_OFFLINETEST_DATA_INCONC( new Identifier( "OFFLINE_TEST_INCONC" ) ),
INFO_OFFLINETEST_DATA_FAIL( new Identifier( "OFFLINE_TEST_FAIL" ) ),
INFO_OFFLINETEST_TP_PATH( new Identifier( "TEST_PURPOSE_PATH" ) ),
INFO_OFFLINETEST_TARGET_STATE( new Identifier( "TARGET_STATE" ) ),
theVerdictKind( VERDICT_UNDEFINED_KIND ),
theSolverKind( SolverDef::SOLVER_CVC4_KIND ),
theTrace( ),
theMergeTrace( ),
theTimedVarsVector( ),
traceInPath( 0 ),
verdictEmitted( false ),
theVerdict( ),
theTestPurpose( ),
theTimeVarInstance( ),
theLeavesECVector( ),
timeReferenceInstance( ),
theObsSignals( ),
theTraceFilter( ),
theErasedNodes( 0 ),
timedFlag( ),
theMainExecutionData( getConfiguration().getMainExecutionData() )
{
//!! NOTHING
}
/*
prototype process::offline_test "offline_test" as &avm::processor.OFFLINETEST is
section PROPERTY
// 'OMEGA' | 'CVC4' | 'Z3' | 'YICES'
@solver = 'CVC4';
endsection PROPERTY
section MERGED_TRACE
@mergedTraceFile="merged_trace.txt";
//optional
@timeVar="spec::system.deltaT";
//optional
@testPurposeFile="test_purpose.txt";
endsection MERGED_TRACE
section TIME_HANDLING
//optional
@currentTime = "inst::system.T";
endsection TIME_HANDLING
// deprecated
section OBSERVABLE_SIGNAL
@machine = "m1";
@port= "p1";
@sens = "?";
@machine = "m2";
@port= "p2";
@sens = "!";
endsection OBSERVABLE_SIGNAL
section OBSERVABLE
@input = "machine_instance1->signal1";
@output = "machine_instance2->signal2";
@input = "machine_instance3->signal1";
@output = "machine_instance3->signal2";
endsection
section CONTROLLABLE
@input = "machine_instance3->signal1";
endsection CONTROLLABLE
endprototype
*/
////////////////////////////////////////////////////////////////////////////////
// CONFIGURE API
////////////////////////////////////////////////////////////////////////////////
bool OfflineTestProcessor::configureImpl()
{
WObject * thePROPERTY = Query::getRegexWSequence(
mParameterWObject, OR_WID2("property", "PROPERTY"));
std::string format;
if( thePROPERTY != WObject::_NULL_ )
{
std::string theSolverID =
Query::getWPropertyString(thePROPERTY, "solver", "");
theSolverKind = SolverDef::toSolver(
theSolverID, SolverDef::DEFAULT_SOLVER_KIND);
//TODO: add possibility to parameterize input format
//for the moment, two formats given as-is:
// the historical format and the basic xlia trace format
format = Query::getWPropertyString(
thePROPERTY, "format", "BASIC#XLIA");
}
else
{
theSolverKind = SolverDef::DEFAULT_SOLVER_KIND;
format = "BASIC#XLIA";
}
WObject * theMergedTrace = Query::getRegexWSequence(
mParameterWObject, OR_WID2("merged_trace", "MERGED_TRACE"));
// WObject * theTimeHandling = Query::getRegexWSequence(
// mParameterWObject , OR_WID2("time_handling", "TIME_HANDLING") );
TraceFactory traceFactory(getConfiguration(), ENV, mParameterWObject);
// Retrieving time info from the xfsp
if( TimedMachine::SYSTEM_VAR_DELTA_TIME != NULL )
{
ExecutableQuery XQuery( getConfiguration() );
timeReferenceInstance = XQuery.getDataByAstElement(
TimedMachine::SYSTEM_VAR_GLOBAL_TIME );
theTimeVarInstance = XQuery.getDataByAstElement(
TimedMachine::SYSTEM_VAR_DELTA_TIME );
timedFlag = true;
}
// TODO: changing time management, getting information directly from the xfsp
else
{
AVM_OS_LOG << "No time parameter found!" << std::endl;
timedFlag = false;
}
/*
else
{
std::string theCurrentTimeVar =
Query::getWPropertyString(theTimeHandling, "currentTime", "");
if( not theCurrentTimeVar.empty() )
{
timeReferenceInstance = RQuery.searchVariable(
theMainExecutionData, theCurrentTimeVar);
if( timeReferenceInstance.invalid() )
{
AVM_OS_WARN << "Unfound currentTime< " << theCurrentTimeVar
<< "> parameter!" << std::endl;
mConfigFlag = false;
}
}
else
{
AVM_OS_WARN << "Unfound currentTime parameter!" << std::endl;
mConfigFlag = false;
}
std::string timeVar =
Query::getWPropertyString(theMergedTrace, "timeVar", "");
if( not timeVar.empty() )
{
theTimeVarInstance = RQuery.searchVariable(
theMainExecutionData, timeVar);
if( theTimeVarInstance.invalid() )
{
AVM_OS_LOG << "Unfound timeVar < " << timeVar << "> parameter!"
<< std::endl;
mConfigFlag = false;
}
}
else
{
AVM_OS_WARN << "Unfound timeVar parameter!" << std::endl;
mConfigFlag = false;
}
}*/
std::string theMergedTracePath =
Query::getWPropertyString(theMergedTrace, "mergedTraceFile", "");
theMergedTracePath = VFS::native_path(
theMergedTracePath, VFS::ProjectSourcePath);
// initializing theTrace
if( not parseMergedTrace(traceFactory, format,
theMergedTracePath, theTrace, theTimeVarInstance) )
{
AVM_OS_WARN << "Error: Error while parsing the trace! " << std::endl;
mConfigFlag = false;
//TODO: check that this is useless and erase it
// initializing theMergeTrace
/*if( not parseMergedTrace(traceFactory,
theMergedTracePath, theMergeTrace, theTimeVarInstance) )
{
AVM_OS_WARN << "Error: Error while parsing merged trace! " << std::endl;
mConfigFlag = false;
}*/
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "The merge trace (sequence of duration/input/output) is: " << std::endl;
theTrace.toStream( AVM_OS_LOG << AVM_TAB_INDENT );
AVM_OS_LOG << END_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
std::string testPurposePath =
Query::getWPropertyString(theMergedTrace, "testPurposeFile", "");
if( not testPurposePath.empty() )
{
testPurposePath = VFS::native_path(
testPurposePath, VFS::ProjectSourcePath);
if( not parseTestPurpose(testPurposePath, theTestPurpose) )
{
AVM_OS_WARN << "Error: Error while parsing test purpose! " << std::endl;
mConfigFlag = false;
}
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "The parsed trace is: " << std::endl;
printTrace(theTrace);
AVM_OS_LOG << "The test purpose (sequence of transition names) is: " << std::endl;
theTestPurpose.toStream( AVM_OS_LOG << AVM_TAB_INDENT );
AVM_OS_LOG << END_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// Configuration of OBSERVABLE SIGNAL
WObject * theObservableSignals = Query::getRegexWSequence(mParameterWObject,
OR_WID2("observable", "OBSERVABLE"), WObject::_NULL_);
//TODO: tests !
// if nothing is declared in the configuration file
// the observable are set to be the signals appearing in the trace
if( (theObservableSignals == WObject::_NULL_) ||
theObservableSignals->hasnoOwnedElement() )
{
AVM_OS_LOG << "Warning : Observable ports are not configured" << std::endl
<< "Deducing observable ports from the trace" <<std::endl;
BFList::raw_iterator< TracePoint > itPoint = theTrace.points.begin();
BFList::raw_iterator< TracePoint > endPoint = theTrace.points.end();
for( ; (itPoint != endPoint) ; ++itPoint )
{
if( (not itPoint->isTime())
&& (not theObsSignals.containsPoint(itPoint, false)))
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "Adding point: " << (*itPoint) << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
theObsSignals.points.append(*itPoint);
}
}
}
// if the observable section contains something
// the observable signals are configured accordingly
else
{
mConfigFlag = traceFactory.configure(theObservableSignals, theObsSignals)
&& mConfigFlag;
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , CONFIGURING )
AVM_OS_LOG << "Configuration of OBSERVABLE SIGNAL: " << std::endl;
theObsSignals.toStream( AVM_OS_LOG << AVM_TAB_INDENT );
AVM_OS_LOG << END_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , CONFIGURING )
// Configuration of CONTROLLABLE SIGNAL
mConfigFlag = theTraceFilter.configure(
ENV, getParameterWObject(), "controllable", "CONTROLLABLE")
&& mConfigFlag;
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , CONFIGURING )
AVM_OS_LOG << "Configuration of CONTROLLABLE SIGNAL: " << std::endl;
theTraceFilter.toStream( AVM_OS_LOG << AVM_TAB_INDENT );
AVM_OS_LOG << END_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , CONFIGURING )
// initialization
traceInPath = 0;
verdictEmitted = false;
theVerdict = "";
theErasedNodes = 0;
return mConfigFlag;
}
//TODO : parameterize input format
bool OfflineTestProcessor::parseMergedTrace(
TraceFactory & aTraceFactory, const std::string & format,
const std::string & filePath,
TraceSequence & aMergeTrace, const BF & theTimeVar)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "File path of merged trace: " << filePath << std::endl
<< "Trace format: " << format << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
std::ifstream fileTrace;
fileTrace.open(filePath.c_str(), std::ifstream::in);
if( fileTrace.is_open() )
{
if( StringTools::startsWith(format,"BASIC") )
{
return( aTraceFactory.parseBasicXliaTrace(
aMergeTrace, fileTrace, theTimeVar) );
}
else //if( StringTools::startsWith(format,"BASIC") )
{
return( aTraceFactory.parseBasicTrace(
aMergeTrace, fileTrace, theTimeVar) );
}
}
else
{
AVM_OS_WARN << "Error: cannot open file "
<< filePath << std::endl;
}
return( false );
}
bool OfflineTestProcessor::parseMergedTrace(
TraceFactory & aTraceFactory, const std::string & filePath,
TraceSequence & aMergeTrace, const BF & theTimeVar)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "File path of merged trace: " << filePath << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
std::ifstream fileTrace;
fileTrace.open(filePath.c_str(), std::ifstream::in);
if( fileTrace.is_open() )
{
return( aTraceFactory.parseBasicTrace(
aMergeTrace, fileTrace, theTimeVar) );
}
else
{
AVM_OS_WARN << "Error: cannot open file "
<< filePath << std::endl;
}
return( false );
}
bool OfflineTestProcessor::parseTestPurpose(
const std::string & filePath, TraceSequence & testPurpose)
{
/*
* This function parses the test purpose given in a file
* as a sequence of transitions.
* If filePath is empty, no test purpose is specified
* The sequence of transitions is stored in the trace element testPurpose
*/
if( filePath == "" )
{
AVM_OS_LOG << "Warning: No test purpose specified! " << std::endl;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "The file path of the test purpose to parse is: "
<< filePath << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
std::ifstream testPurposeFile;
testPurposeFile.open(filePath.c_str(), std::ifstream::in);
if( testPurposeFile.is_open() )
{
std::string oneLine;
while (testPurposeFile.good())
{
std::getline(testPurposeFile, oneLine);
TraceFactory::appendTransitionPoint(
getConfiguration(), testPurpose, oneLine);
}
}
else
{
AVM_OS_WARN << "Error: Error while reading test purpose file "
<< filePath << std::endl;
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// REPORT API
////////////////////////////////////////////////////////////////////////////////
void OfflineTestProcessor::reportDefault(OutStream & os) const
{
reportHeader(os, "AVM OFF-LINE TEST ");
os << EMPHASIS(theVerdict, '=', 80);
}
////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESS API
////////////////////////////////////////////////////////////////////////////////
bool OfflineTestProcessor::preprocess()
{
AVM_OS_WARN << "OfflineTestProcessor::preprocess()" << std::endl;
return( true );
}
////////////////////////////////////////////////////////////////////////////////
// PRE-FILTER API
////////////////////////////////////////////////////////////////////////////////
bool OfflineTestProcessor::AssignValuesIfObservable(
ExecutionContext & anExecutionContext, TraceSequence & localTrace)
{
bool valueAssigned = false;
if( anExecutionContext.hasIOElementTrace() )
{
const BF & theBF = anExecutionContext.getIOElementTrace();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "OFFLINE TEST:: About to parse the trace: " << std::endl
<< theBF.toString() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
//TODO : change hasIO for matchesIO in a smart way
valueAssigned = hasIO(theBF, anExecutionContext, localTrace);
//valueAssigned = matches(theBF, anExecutionContext, localTrace);
}
return valueAssigned;
}
/*
bool OfflineTestProcessor::matches(const BF & anElement,
ExecutionContext & anExecutionContext, TraceSequence & localTrace)
{
bool valueAssigned = false;
if( anElement.is< AvmCode >() )
{
AvmCode * theAC = anElement.to_ptr< AvmCode >();
AvmCode::iterator it = theAC->begin();
switch( theAC->getAvmOpCode() )
{
case AVM_OPCODE_PARALLEL :
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
}
break;
}
case AVM_OPCODE_SEQUENCE :
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
else
{
// valueAssigned = false;
// break;
}
}
break;
}
default:
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
}
break;
}
}
}
else if( anElement.is< ExecutionConfiguration >() )
{
ExecutionConfiguration * theEC = anElement.to_ptr< ExecutionConfiguration >();
valueAssigned = hasIO( theEC, anExecutionContext, localTrace);
}
return valueAssigned;
} */
bool OfflineTestProcessor::hasIO(const BF & anElement,
ExecutionContext & anExecutionContext, TraceSequence & localTrace)
{
bool valueAssigned = false;
if( anElement.is< AvmCode >() )
{
AvmCode * theAC = anElement.to_ptr< AvmCode >();
AvmCode::iterator it = theAC->begin();
switch( theAC->getAvmOpCode() )
{
case AVM_OPCODE_PARALLEL :
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
}
break;
}
case AVM_OPCODE_SEQUENCE :
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
else
{
// valueAssigned = false;
// break;
}
}
break;
}
default:
{
for( ; it != theAC->end() ; ++it )
{
if( hasIO( (*it), anExecutionContext, localTrace) )
{
valueAssigned = true;
}
}
break;
}
}
}
else if( anElement.is< ExecutionConfiguration >() )
{
ExecutionConfiguration * theEC = anElement.to_ptr< ExecutionConfiguration >();
valueAssigned = hasIO( theEC, anExecutionContext, localTrace);
}
return valueAssigned;
}
bool OfflineTestProcessor::hasIO(
ExecutionConfiguration * anExecutionConfiguration,
ExecutionContext & anExecutionContext, TraceSequence & localTrace)
{
// TODO: here, the exec configuration is the main? one.
// Maybe we will need to take into account cases where the input/outputs
// are considered from a sub-machine point of view.
bool valueAssigned = false;
if( anExecutionConfiguration->isAvmCode() )
{
const BFCode & theAC = anExecutionConfiguration->getAvmCode();
AVM_OS_LOG << "OfflineTestProcessor::hasIO < theAC > : "
<< theAC.str() << std::endl;
switch( theAC->getAvmOpCode() )
{
case AVM_OPCODE_INPUT :
{
if( theAC->first().is< InstanceOfPort >())
{
InstanceOfPort * ioPort = theAC->first().to_ptr< InstanceOfPort >();
if( ioPort->hasAliasTarget() )
{
ioPort = ioPort->getAliasTarget()->as< InstanceOfPort >();
}
// the first item in the trace could be a delay,
// (but it may happen that here are two consecutive actions)
// (but there are never two consecutive time delays)
// so we compare ports with the first and second entries in the localObs
// we retrieve the next action in the localTrace
// either it is in the first TracePoint
// or the first TracePoint is a delay and so it must be the next one
TracePoint * aTracePoint = NULL;
if( localTrace.points.nonempty() )
{
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
if( aTracePoint->isTime() && localTrace.points.populated() )
{
aTracePoint = localTrace.points.second().to_ptr< TracePoint >();
}
}
if( (aTracePoint != NULL)
&& (ioPort->getNameID() == aTracePoint->object->getNameID())
&& ((aTracePoint->op == AVM_OPCODE_INPUT)
||(aTracePoint->op == AVM_OPCODE_INPUT_ENV)))
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST:: Input found on port: "
<< ioPort->getNameID() << std::endl
<< "with machine : " << ioPort->getRuntimeContainerRID().str() << std::endl
<< "with machine 2 : " << anExecutionConfiguration->getRuntimeID().str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = lookupValue(theAC, anExecutionContext,
anExecutionConfiguration, ioPort,
theAC->getAvmOpCode(), localTrace);
break;
}
const ExecutionData & anED = anExecutionContext.refExecutionData();
RuntimeID theRID = anExecutionConfiguration->getRuntimeID();
const RoutingData & ioRD = AvmCommunicationFactory::
searchInputRoutingData(anED, ioPort, theRID);
if( ioRD.valid() )
{
if( ioRD.getProtocol() == ComProtocol::PROTOCOL_ENVIRONMENT_KIND )
{
// we retrieve the next action in the localTrace
// either it is in the first TracePoint
// or the first TracePoint is a delay and so it must be the next one
TracePoint * aTracePoint = NULL;
if( localTrace.points.nonempty() )
{
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
if( aTracePoint->isTime() && localTrace.points.populated() )
{
aTracePoint = localTrace.points.second().to_ptr< TracePoint >();
}
}
if( (aTracePoint != NULL)
&& (ioPort->getNameID() == aTracePoint->object->getNameID())
&& ((aTracePoint->op == AVM_OPCODE_INPUT)
||aTracePoint->op == AVM_OPCODE_INPUT_ENV))
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST:: input from environment on port: "
<< ioPort->getNameID() << std::endl
<< "with machine : " << ioPort->getRuntimeContainerRID().str() << std::endl
<< "with machine 2 : " << anExecutionConfiguration->getRuntimeID().str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = lookupValue(theAC,
anExecutionContext,
anExecutionConfiguration,
ioPort, theAC->getAvmOpCode(),
localTrace);
}
}
break;
}
}
break;
}
case AVM_OPCODE_OUTPUT :
{
if( theAC->first().is< InstanceOfPort >() )
{
InstanceOfPort * ioPort = theAC->first().to_ptr< InstanceOfPort >();
if( ioPort->hasAliasTarget() )
{
ioPort = ioPort->getAliasTarget()->as< InstanceOfPort >();
}
// we retrieve the next action in the localTrace
// either it is in the first TracePoint
// or the first TracePoint is a delay and so it must be the next one
TracePoint * aTracePoint = NULL;
if( localTrace.points.nonempty() )
{
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
if( aTracePoint->isTime() && localTrace.points.populated() )
{
aTracePoint = localTrace.points.
second().to_ptr< TracePoint >();
}
}
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "OFFLINE TEST:: TracePoint considered: " << std::endl;
// aTracePoint->toStream(AVM_OS_LOG << AVM_TAB_INDENT);
// AVM_OS_LOG << "Compiled form name :" << ioPort->getNameID() << std::endl
// << "TracePoint object Id :" <<aTracePoint->object->getNameID() << std::endl
// << "TracePoint operator :" << aTracePoint->to_string(aTracePoint->op) << std::endl;
// AVM_OS_LOG << END_INDENT << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( (aTracePoint != NULL)
&& (ioPort->getNameID() == aTracePoint->object->getNameID())
&& ((aTracePoint->op == AVM_OPCODE_OUTPUT)
||aTracePoint->op == AVM_OPCODE_OUTPUT_ENV))
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST:: Output found on port: "
<< ioPort->getNameID() << std::endl
<< "with machine : " << ioPort->getRuntimeContainerRID().str() << std::endl
<< "with machine 2 : " << anExecutionConfiguration->getRuntimeID().str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = lookupValue(theAC, anExecutionContext,
anExecutionConfiguration, ioPort,
theAC->getAvmOpCode(), localTrace);
break;
}
const ExecutionData & anED = anExecutionContext.refExecutionData();
RuntimeID theRID = anExecutionConfiguration->getRuntimeID();
const RoutingData & ioRD = AvmCommunicationFactory::
searchOutputRoutingData(anED, ioPort, theRID);
if( ioRD.valid() )
{
if( ioRD.getProtocol() == ComProtocol::PROTOCOL_ENVIRONMENT_KIND )
{
// we retrieve the next action in the localTrace
// either it is in the first TracePoint
// or the first TracePoint is a delay and so it must be the next one
TracePoint * aTracePoint = NULL;
if( localTrace.points.nonempty() )
{
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
if( aTracePoint->isTime() && localTrace.points.populated() )
{
aTracePoint = localTrace.points.second().to_ptr< TracePoint >();
}
}
if( (aTracePoint != NULL)
&& (ioPort->getNameID() == aTracePoint->object->getNameID())
&& ((aTracePoint->op == AVM_OPCODE_OUTPUT)
||aTracePoint->op == AVM_OPCODE_OUTPUT_ENV))
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST:: output to environment on port: "
<< ioPort->getNameID() << std::endl
<< "with machine : " << ioPort->getRuntimeContainerRID().str() << std::endl
<< "with machine 2 : " << anExecutionConfiguration->getRuntimeID().str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = lookupValue(theAC,
anExecutionContext,
anExecutionConfiguration,
ioPort, theAC->getAvmOpCode(),
localTrace);
}
}
break;
}
}
break;
}
case AVM_OPCODE_ASSIGN_NEWFRESH :
{
valueAssigned = false;
break;
}
default :
{
valueAssigned = false;
// Pas de récursion car anExecutionConfiguration est atomique du point de vue la I/O-Trace
// for(AvmCode::iterator it = theAC->begin() ; it != theAC->end() ; ++it )
// {
// if( hasIO( (*it), anExecutionContext, localTrace) )
// {
// valueAssigned = true;
// }
// }
break;
}
}
}
return valueAssigned;
}
bool OfflineTestProcessor::updateTime(
TracePoint * aTracePoint,
ExecutionContext & anExecutionContext,
TraceSequence * localTrace)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Time passing... add time constraint, input" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
const BF & currentTimeVar = ENV.getRvalue(
anExecutionContext.getAPExecutionData(),
anExecutionContext.refExecutionData().getSystemRID(),
timeReferenceInstance.to_ptr< InstanceOfData >());
// assign the delay to the difference of currtime - ref time
BF buildValue = ENV.getBuilder().build(
theMainExecutionData, aTracePoint->val(0));
//PathConditionProcessor::addPathTimedCondition(
// anExecutionContext.getExecutionData(),
anExecutionContext.getAPExecutionData().mwsetPathTimedCondition(
ExpressionConstructor::andExpr(
anExecutionContext.refExecutionData().getPathTimedCondition(),
ExpressionConstructor::eqExpr(
ExpressionConstructor::minusExpr(currentTimeVar,
anExecutionContext.getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getTimeReference()),
buildValue)));
if( not SolverFactory::isSatisfiable(theSolverKind,
anExecutionContext.refExecutionData().getPathTimedCondition()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "3. FAIL: path constraint not satisfiable (delay)" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return false;
}
// remove read val
localTrace->points.remove_first();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "And the timed constraint is "
<< anExecutionContext.refExecutionData().getPathTimedCondition().str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return true;
}
bool OfflineTestProcessor::lookupValue(
AvmCode * anAC, ExecutionContext & anExecutionContext,
ExecutionConfiguration * anExecutionConfiguration,
InstanceOfPort * aPort, AVM_OPCODE avmOpcode,
TraceSequence & localTrace)
{
// assign the respective value (if found) to its respective variable
bool valueAssigned = false;
TracePoint * aTracePoint = NULL;
while( true )
{
avm_size_t nbParam = aPort->getParameterCount();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Number of parameters:" << nbParam << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
// considering communication actions
//TODO: consider other observable actions (such as variable assignations) ?
if( (avmOpcode == AVM_OPCODE_OUTPUT) || (avmOpcode == AVM_OPCODE_INPUT) )
{
// compare action in tree with local obs: one or two steps
// 1. (conditional) : if the first value is a time var:
// assign the time to the data var
// and delete the trace point from the trace
// 2. compare action with trace element
if( aTracePoint->isTime() &&
( (theTimeVarInstance == aTracePoint->object) /*||
(theTimeVarInstance->getNameID() == aTracePoint->object->getNameID())*/ ) )
{
// 1. case where first value is a time var
valueAssigned = updateTime(aTracePoint,
anExecutionContext, &localTrace);
if( not valueAssigned)
{
break;
}
//localTrace.points.remove_first();
}
// Step 2 : compare action in symbolic tree with trace element
//now reading what should be a signal
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "The port in the trace is " << aTracePoint->object->str() << std::endl
<< "And the port is " << aPort->getNameID()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
// now reading values to be compared
// the signal should correspond with the value in
// the trace, else it is simply not removed
if( aTracePoint->object->getNameID() == aPort->getNameID() )
{
//checking direction of signal
if( (avmOpcode == AVM_OPCODE_OUTPUT) &&
((aTracePoint->op == AVM_OPCODE_INPUT) ||
(aTracePoint->op == AVM_OPCODE_INPUT_ENV)) )
{
AVM_OS_LOG << "OFFLINE TEST: WARNING! input when expecting output!"
<< std::endl;
valueAssigned = false;
break;
}
if( (avmOpcode == AVM_OPCODE_INPUT) &&
((aTracePoint->op == AVM_OPCODE_OUTPUT) ||
(aTracePoint->op == AVM_OPCODE_OUTPUT_ENV)) )
{
AVM_OS_LOG << "OFFLINE TEST: WARNING! output when expecting input!"
<< std::endl;
valueAssigned = false;
break;
}
//each of the parameters must match
bool matchingParams = true;
//int paramNb = 0;
if( matchingParams )
{
RuntimeQuery RQuery( getConfiguration() );
for( avm_size_t i = 0 ; matchingParams && (i < nbParam) ; ++i )
{
if( anAC->get(i+1).is< InstanceOfData >() )
{
BF foundVar = RQuery.searchVariable(
anExecutionContext.refExecutionData(),
anExecutionConfiguration->getRuntimeID(),
anAC->get(i+1) );
if( foundVar.valid() )
{
matchingParams = assignValue(
anAC, anExecutionContext,
foundVar, aTracePoint, i );
}
else
{
AVM_OS_LOG << "lookupValue(...): "
"Unfound symbolic parameter :> "
<< anAC->get(i+1) << std::endl;
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "cufi: " << anAC->get(i+1).to_ptr< InstanceOfData >()->getAstFullyQualifiedNameID() << std::endl
<< "port: " << str_header( aPort ) << std::endl
<< "rid : " << str_header( anExecutionConfiguration->getRuntimeID() ) << std::endl
<< "com : " << str_header( anExecutionConfiguration->getRuntimeID().getCommunicator(aPort) ) << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
}
else
{
matchingParams = assignValue(
anAC, anExecutionContext,
BF::REF_NULL, aTracePoint, i );
}
/*
if( anAC->get(i+1).is< InstanceOfData >() )
{
valueAssigned = assignValue(anAC, anExecutionContext,
aTracePoint, i);
}
else
// if( anAC->get(i+1).isNumber()
// || anAC->get(i+1).isBoolean()
// || anAC->get(i+1).isBuiltinString()
// || anAC->get(i+1).isEnumSymbol())
//TODO: check whether this is not problematic (certain types, machine, etc)
{
matchingParams = ((aTracePoint->val(i) == anAC->get(i+1)) && matchingParams);
}*/
}
if( matchingParams )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: com action corresponds to trace, delete it" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
localTrace.points.remove_first();
valueAssigned = true;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: WARNING: com action : " ;
for( avm_size_t i = 0 ; i < nbParam; ++i )
{
AVM_OS_LOG << " " << anAC->get(i+1).str() ;
}
//aPort->getParameter(0)
AVM_OS_LOG << " does not correspond to trace : "
<< aTracePoint->value.str()
<< " , do not delete it (but deleting for the moment)"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = false;
anExecutionContext.getAPExecutionData().
mwsetPathCondition( ExpressionConstant::BOOLEAN_FALSE );
}
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: WARNING : number of parameters expected" << nbParam
<< "while actual number of parameters given in the trace is"
<< aTracePoint->valCount() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
break;
}
}
/*
//Now, treat case where local obs is an input
else if( avmOpcode == AVM_OPCODE_INPUT )
{
// check input in tree with local obs: on or two steps
// 1. if first element in trace is a time var
// assign time data and move on
// 2. compare element in trace against input
if( aTracePoint->isTime() &&
(theTimeVarInstance->getNameID() == aTracePoint->object->getNameID()) )
{
valueAssigned = updateTime(aTracePoint, anExecutionContext, &localTrace);
if( valueAssigned == false )
{
break;
}
localTrace.points.remove_first();
}
//now reading what should be a signal
aTracePoint = localTrace.points.first().to_ptr< TracePoint >();
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "The port in the trace is " << aTracePoint->object->str() << std::endl
// << "And the port is " << aPort->getNameID()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// now reading input value to be compared
if( aTracePoint->object->getNameID() == aPort->getNameID() )
{
if( (aTracePoint->op == AVM_OPCODE_OUTPUT) ||
(aTracePoint->op == AVM_OPCODE_OUTPUT_ENV) )
{
AVM_OS_LOG << "OFFLINE TEST: WARNING! output when expecting input!"
<< std::endl;
valueAssigned = false;
break;
}
// the input should correspond with the value in
// the trace, else it is simply not removed
bool matchingParams = (aTracePoint->valCount() == nbParam);
if( matchingParams )
{
for( avm_size_t i = 0 ; matchingParams && (i < nbParam) ; ++i )
{
//TODO: add conditional numeric/symbolic
if( anAC->get(i+1).is< InstanceOfData >() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Assigning value: " << aTracePoint->val(i) << "to variable: "
<< anAC->get(i+1).to_ptr< InstanceOfData >()->getNameID()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = assignValue(anAC,
anExecutionContext, aTracePoint, i);
}
else if( anAC->get(i+1).isNumber()
|| anAC->get(i+1).isBoolean()
|| anAC->get(i+1).isBuiltinString()
|| anAC->get(i+1).isEnumSymbol() )
{
matchingParams = ((aTracePoint->val(i) ==
anAC->get(i+1)) && matchingParams);
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Unexpected Kind: " << anAC->get(i+1).classKindName() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
break;
}
}
if( matchingParams)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: output corresponds to trace, delete it" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
localTrace.points.remove_first();
valueAssigned = true;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: WARNING: input : " ;
for( avm_size_t i = 0 ; i < nbParam; ++i )
{
AVM_OS_LOG << "\t" << anAC->get(i+1).str() ;
}
//aPort->getParameter(0)
AVM_OS_LOG << " does not correspond to trace : "
<< aTracePoint->value.str()
<< " , do not delete it (but deleting for the moment)" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = false;
//
// TODO Modification de la path condition sans risque dans le smart pointer ExecutionData
//
// if( not PathConditionProcessor::addPathCondition(
// anExecutionContext.getAPExecutionData(),
// ExpressionConstant::BOOLEAN_FALSE) )
// {
// //!! INSATISFIABLE PATH CONDITION
// }
anExecutionContext.getAPExecutionData().
mwsetPathCondition( ExpressionConstant::BOOLEAN_FALSE );
}
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: WARNING : number of parameters expected" << nbParam
<< "while actual number of parameters given in the trace is"
<< aTracePoint->valCount() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
break;
}
}
break;*/
}
if( valueAssigned )
{
// Sometimes, the constraint is no longer valid, but it still appears
// in the graph
if( not SolverFactory::isSatisfiable(theSolverKind,
anExecutionContext.refExecutionData().getPathCondition()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Warning! the path constraint after assigning the values is false !"
<< "\n\t==> returning false, so the EC children won't be evaluated anymore !"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = false;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "The constraint is satisfied !" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
}
return valueAssigned;
}
bool OfflineTestProcessor::assignValue(AvmCode * anAC,
ExecutionContext & anExecutionContext,
ExecutionConfiguration * anExecutionConfiguration,
InstanceOfPort * aPort,
TraceSequence & localTrace, int offset)
{
// look for the respective value:
// simple search on the vector of pair of values until we find
// a match on the variable name; if found, "assign" the value...
// The value is assigned as a constraint in the Path Condition
TracePoint * aTracePoint = localTrace.points.first().to_ptr<TracePoint>();
if( aTracePoint->isTime() &&
( (theTimeVarInstance == aTracePoint->object) /*||
(theTimeVarInstance->getNameID() == aTracePoint->object->getNameID())*/ ) )
{
// since the traces are of the form DELAY.ACTION, and since we may have consecutive
// inputs/outputs without delays in between (structures of data),
// if we are in such a case (a trace of the form 5.a?.a?), we verify that
// the FIRST item in the trace is a delay, and that the SECOND one is the input/output
// that we are expecting to see.
// This happens only once, since for the case when the trace is just a?
// (and 5.a? have been read), we compare directly with the FIRST item
// of the trace
// TODO: change this to take outputs into account (next step)
// if there is a passage of time observation, just add it
// to the path condition of the node (EC)
// emit verdicts according to output
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Assign value: Time passing... add time constraint" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
const BF & currentTimeVar = ENV.getRvalue(
anExecutionContext.getAPExecutionData(),
anExecutionContext.refExecutionData().getSystemRID(),
timeReferenceInstance.to_ptr< InstanceOfData >());
// assign the delay to the difference of currtime - ref time
BF buildValue = ENV.getBuilder().build(
theMainExecutionData, aTracePoint->val(0));
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "the vars are: curr timevar: "
<< currentTimeVar.str() << std::endl
<< "reference time:> " << std::endl
<< "\tvar : " << anExecutionContext.getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getTimeReference().str()
<< std::endl
<< "\tvalue : " << buildValue.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
anExecutionContext.getAPExecutionData().mwsetPathTimedCondition(
ExpressionConstructor::andExpr(
anExecutionContext.refExecutionData().getPathTimedCondition(),
ExpressionConstructor::eqExpr(
ExpressionConstructor::minusExpr(currentTimeVar,
anExecutionContext.getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getTimeReference()),
buildValue)));
if( not SolverFactory::isSatisfiable(theSolverKind,
anExecutionContext.refExecutionData().getPathTimedCondition()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "4. FAIL: path constraint not satisfiable due to delay"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return false;
}
localTrace.points.remove_first();
aTracePoint = localTrace.points.first().to_ptr<TracePoint>();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "And the second timed constraint is "
<< anExecutionContext.refExecutionData().getPathTimedCondition().str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
// everything is OK if the first value in the trace to be read corresponds
// to the one that we are looking for, else???
avm_size_t nbParam = aPort->getParameterCount();
if( (aTracePoint->object->getNameID() == aPort->getNameID()) &&
(nbParam == aTracePoint->valCount()) )
{
//int nbParam = aPort->getParameterCount();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Found in its place, variable: ";
for( avm_size_t i = 0 ; i < nbParam ; ++i )
{
AVM_OS_LOG << "\t" << anAC->get(i+1).to_ptr< InstanceOfData >()->getFullyQualifiedNameID();
}
AVM_OS_LOG << " in port " << aPort->getNameID()
<< " == " << aTracePoint->object->str() << std::endl
<< "with machine 3 : " << aPort->getRuntimeContainerRID().getNameID() << std::endl
<< "with machine 4 : " << anExecutionConfiguration->getRuntimeID().getNameID() << std::endl
<< "with machine 5 : " << anExecutionConfiguration->getRuntimeID().
getCommunicator(aPort).getNameID() << std::endl
<< "About to assign value:> " << aTracePoint->value.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
RuntimeQuery RQuery( getConfiguration() );
for( avm_size_t i = 0 ; i < nbParam ; ++i )
{
// the value is stored in the trace point and accessed through the val method
BF buildValue = ENV.getBuilder().build(
theMainExecutionData, aTracePoint->val(i));
//TODO: check whether there is no issue with the management of strings
if( aTracePoint->val(i).isBuiltinString() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Assigning a string ! " << aTracePoint->val(i).str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else
{
// TODO : tests
if( not PathConditionProcessor::addPathCondition(
anExecutionContext.getAPExecutionData(),
ExpressionConstructor::eqExpr(anAC->get(i+1), buildValue),
false) )
{
//!! INSATISFIABLE PATH CONDITION
return false; // ??? TODO
}
}
BF variableInstance = RQuery.searchVariable(
anExecutionContext.refExecutionData(),
anExecutionConfiguration->getRuntimeID(), anAC->get(i+1) );
if( variableInstance.valid() )
{
// Assign the value
ENV.setRvalue(anExecutionContext.getAPExecutionData(),
variableInstance.to_ptr< InstanceOfData >(), buildValue);
}
else
{
AVM_OS_LOG << "assignValue(...): Unfound symbolic parameter :> "
<< anAC->get(i+1) << std::endl;
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "cufi: "
<< anAC->get(i+1).to_ptr< InstanceOfData >()->getAstFullyQualifiedNameID() << std::endl
<< "port: " << str_header( aPort ) << std::endl
<< "rid : " << str_header( anExecutionConfiguration->getRuntimeID() ) << std::endl
<< "com : " << str_header( anExecutionConfiguration->getRuntimeID().getCommunicator(aPort) )
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
}
localTrace.points.remove_first();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "After observing the local obs trace of size: "
<< localTrace.points.size() << std::endl;
printTrace(localTrace);
AVM_OS_LOG << "And the all constraint is :>\n\t"
<< anExecutionContext.refExecutionData().getAllPathCondition().str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return true;
}
else if( nbParam != aTracePoint->valCount() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OFFLINE TEST: WARNING : number of parameters expected" << nbParam
<< "while actual number of parameters given in the trace is"
<< aTracePoint->valCount() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Input/Output not expected ("
<< anAC->get(1).to_ptr< InstanceOfData >()->getAstFullyQualifiedNameID()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
return false;
}
bool OfflineTestProcessor::assignValue(
AvmCode * anAC, ExecutionContext & anExecutionContext,
const BF & variableInstance, TracePoint * aTracePoint, int paramNb)
{
bool valueAssigned =false;
// the value is stored in the trace point and accessed through the val method
if(anAC->get(paramNb+1).isBuiltinString())
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Checking string equality! "
<< anAC->get(paramNb+1).str()
<< " =? "
<< aTracePoint->val(paramNb).str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = (aTracePoint->val(paramNb) == anAC->get(paramNb+1));
}
else if(anAC->get(paramNb+1).isIdentifier())
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Checking that identifiers match: "
<< anAC->get(paramNb+1).str()
<< " =? "
<< aTracePoint->val(paramNb).str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned =
(aTracePoint->val(paramNb).to_ptr< Identifier >()->getValue()
== anAC->get(paramNb+1).to_ptr< Identifier >()->getValue());
}
//gestion du type machine
else if( anAC->get(paramNb+1).is< RuntimeID >() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Checking machine equality: "
<< anAC->get(paramNb+1).str()
<< " =? "
<< aTracePoint->val(paramNb).str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
RuntimeID machine = anAC->get(paramNb+1).as_bf< RuntimeID >();
valueAssigned = (aTracePoint->val(paramNb).isTEQ(machine.getInstance()));
}
// Const value
// TODO : testing equality between value in trace and at runtime properly
/*
else if( anAC->get(paramNb+1).isConstValue() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Checking parameter equality: "
<< anAC->get(paramNb+1).str()
<< " =? "
<< aTracePoint->val(paramNb).str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
valueAssigned = (aTracePoint->val(paramNb).isEQ(anAC->get(paramNb+1)));
}*/
// Symbolic execution Value
else
{
BF buildValue = ENV.getBuilder().build(
theMainExecutionData, aTracePoint->val(paramNb));
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Assigning value: " << aTracePoint->val(paramNb)
<< " to variable: " << anAC->get(paramNb+1).str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
//TODO: check whether there is no issue with the management of strings
if( aTracePoint->val(paramNb).isBuiltinString() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Assigning a string ! "
<< aTracePoint->val(paramNb).str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else {
if( not PathConditionProcessor::addPathCondition(
anExecutionContext.getAPExecutionData(),
ExpressionConstructor::eqExpr(anAC->get(paramNb+1), buildValue),
false ) )
//TODO : testing whether adding parameter false is better
{
//!! INSATISFIABLE PATH CONDITION
return false; // ??? TODO
}
}
return true;
}
return valueAssigned;
}
//bool OfflineTestProcessor::assignValue(AvmCode * anAC,
// ExecutionContext & anExecutionContext,
// ExecutionConfiguration * anExecutionConfiguration,
// BF dataVar, InstanceOfPort * aPort,
// TraceSequence & localTrace, int offset)
//{
// // look for the respective value:
// // simple search on the vector of pair of values until we find
// // a match on the variable name; if found, "assign" the value...
// // The value is assigned as a constraint in the Path Condition
// TracePoint * aTracePoint = localTrace.points.first().to_ptr<TracePoint>();
// if( aTracePoint->isTime() &&
// (theTimeVarInstance->getNameID() == aTracePoint->object->getNameID()) )
// {
// // since the traces are of the form DELAY.ACTION, and since we may have consecutive
// // inputs/outputs without delays in between (structures of data),
// // if we are in such a case (a trace of the form 5.a?.a?), we verify that
// // the FIRST item in the trace is a delay, and that the SECOND one is the input/output
// // that we are expecting to see.
// // This happens only once, since for the case when the trace is just a?
// // (and 5.a? have been read), we compare directly with the FIRST item
// // of the trace
//
// // TODO: change this to take outputs into account (next step)
// // if there is a passage of time observation, just add it
// // to the path condition of the node (EC)
// // emit verdicts according to output
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "Assign value: Time passing... add time constraint" << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
//
// const BF & currentTimeVar = ENV.getRvalue(
// anExecutionContext.getAPExecutionData(),
// anExecutionContext.refExecutionData().getSystemRID(),
// timeReferenceInstance);
//
// // assign the delay to the difference of currtime - ref time
// BF buildValue = ENV.getBuilder().build(
// theMainExecutionData, aTracePoint->val(0));
//
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "the vars are: curr timevar: "
// << currentTimeVar.str() << std::endl
// << "reference time:> " << std::endl
// << "\tvar : " << anExecutionContext.getUniqInformation()->
// getUniqOfflineTestProcessorInfo()->getTimeReference().str() << std::endl
// << "\tvalue : " << buildValue.str() << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
//
// anExecutionContext.getAPExecutionData().mwsetPathTimedCondition(
// ExpressionConstructor::andExpr(
// anExecutionContext.refExecutionData().getPathTimedCondition(),
// ExpressionConstructor::eqExpr(
// ExpressionConstructor::minusExpr(currentTimeVar,
// anExecutionContext.getUniqInformation()->
// getUniqOfflineTestProcessorInfo()->getTimeReference()),
// buildValue)));
//
// if( not SolverFactory::isSatisfiable(theSolverKind,
// anExecutionContext.refExecutionData().getPathTimedCondition()) )
// {
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "4. FAIL: path constraint not satisfiable due to delay"
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// return false;
// }
//
//
// localTrace.points.remove_first();
// aTracePoint = localTrace.points.first().to_ptr<TracePoint>();
//
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "And the second timed constraint is "
// << anExecutionContext.refExecutionData().getPathTimedCondition().str()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// }
//
// // everything is OK if the first value in the trace to be read corresponds
// // to the one that we are looking for, else???
//
// if( aTracePoint->object->getNameID() == aPort->getNameID() )
// {
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "Found in its place, variable: "
// << dataVar.to_ptr< InstanceOfData >()->getFullyQualifiedNameID()
// << " in port " << aPort->getNameID()
// << " == " << aTracePoint->object->str() << std::endl
// << "with machine 3 : " << aPort->getRuntimeContainerRID().getNameID() << std::endl
// << "with machine 4 : " << anExecutionConfiguration->getRuntimeID().getNameID() << std::endl
// << "with machine 5 : " << anExecutionConfiguration->getRuntimeID().
// getCommunicator(aPort).getNameID() << std::endl
// << "About to assign value:> " << aTracePoint->val(0).str() << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
//
// // for the moment, the value is stored in the third position of the list
// // the value is stored in the trace point and accessed through the val method
// BF buildValue = ENV.getBuilder().build(
// theMainExecutionData, aTracePoint->val(0));
//
////TODO: check whether there is no issue with the management of strings
// if( aTracePoint->val(0).isBuiltinString() )
// {
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "Assigning a string ! "
// //<<dataVar.to_ptr< InstanceOfData >()->getAstFullyQualifiedNameID() << std::endl
// //<< aTracePoint->val(0).str()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// }
// else {
// anExecutionContext.getAPExecutionData().mwsetPathCondition(
// ExpressionConstructor::andExpr(
// anExecutionContext.refExecutionData().getPathCondition(),
// ExpressionConstructor::eqExpr(dataVar, buildValue)));
// }
//
// BF variableInstance = ENV.getBuilder().searchSymbolData(
// theMainExecutionData, dataVar->getAstFullyQualifiedNameID());
//
// // Assign the value
// ENV.setRvalue(anExecutionContext.getAPExecutionData(),
// variableInstance, buildValue);
// localTrace.points.remove_first();
//
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "After observing the local obs trace of size: "
// << localTrace.points.size() << std::endl;
// printTrace(localTrace);
//
// AVM_OS_LOG << "And the all constraint is :>\n\t"
// << anExecutionContext.refExecutionData().getAllPathCondition().str()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
//
// return true;
// }
// else
// {
//
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "Input/Output not expected (" <<
// dataVar.to_ptr< InstanceOfData >()->getAstFullyQualifiedNameID()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// }
//
// return false;
//}
/*bool OfflineTestProcessor::reAssignValue(AvmCode * anAC,
// ExecutionContext & anExecutionContext,
// BF aValue, InstanceOfPort * aPort,
// VectorOfPairOfVariableValue * aTable, int offset)
//{
// This version of the method is for changing the value
// "associated" with port aPort
TripleOfPortVariableOffset aTuple;
VectorOfPairOfVariableValue::iterator it = aTable->begin();
VectorOfPairOfVariableValue::iterator itend = aTable->end();
// loop iterating on the vector of variable/values (parameters file)
for( ; it != itend ; ++it)
{
// loop iterating on the vector of modified variables
for (size_t i=0 ; i < theVectorOfPortVariableOffset.size() ; ++i )
{
aTuple = theVectorOfPortVariableOffset[i];
if( aPort != aTuple.get<0>().to_ptr< InstanceOfPort >() )
{
continue;
}
AVM_OS_LOG << "search mapping " << std::endl;
if( operator==(aTuple, boost::make_tuple(
aPort,(*it).first().to_ptr< InstanceOfData >(), offset)) )
{
AVM_OS_LOG << "mapping found!!! "
<< aTuple.get<0>().to_ptr< InstanceOfPort >().getFullyQualifiedNameID()
<< "," << aTuple.get<1>().to_ptr< InstanceOfData >().str()
<< "," << aTuple.get<2>() << " con " << aPort->str()
<< "," << (*it).first()->to< InstanceOfData >()->str()
<< "," << offset << std::endl;
// Create a new simbolic var and assign the constraint
AVM_OS_LOG << "viendo ahora la symbolic var... para "
<< (*it).first()->getAstFullyQualifiedNameID() << std::endl
<< "viendo ahora la symbolic var... para "
<< (*it).first()->getAstNameID() << std::endl;
InstanceOfMachine * theMainSpecification =
getConfiguration().getExecutableSystem().getSystemInstance();
if( theMainSpecification != NULL )
{
AVM_OS_LOG << "al menos no es null \n";
}
Variable * aVar = theMainSpecification->getExecutable()->
getAstMachine()->getVariable( (*it).first()->getAstNameID() );
const BF & ripvalue = ENV.getRvalue(anExecutionContext.getAPExecutionData(),
anExecutionContext.refExecutionData().getRuntimeID(theMainSpecification),
(*it).first().to_ptr< InstanceOfData >());
if( aVar != NULL )
{
InstanceOfData * varGlobalTime = theMainSpecification->
getExecutable()->getAllData().rawByCompiled(aVar);
AVM_OS_LOG << "VEMOSNOOOSSSS.........; "
<< varGlobalTime->getFullyQualifiedNameID() << std::endl;
const BF & rvalue = ENV.getRvalue(anExecutionContext.getAPExecutionData(),
anExecutionContext.refExecutionData().getRuntimeID(theMainSpecification),
varGlobalTime);
AVM_OS_LOG << "VEMOSNOs MAS : " << rvalue.str();
}
if( ripvalue.valid() )
{
AVM_OS_LOG << "prvobemos a ver : " << ripvalue.str() << std::endl;
}
AVM_OS_LOG << "ES NULLLL \n";
// tuple found, replace with new value
BF buildValue = ENV.getBuilder().build(theMainExecutionData, aValue);
ENV.setRvalue(anExecutionContext.getAPExecutionData(),
(*it).first(), buildValue);
return true;
}
}
}
// return false;
//}
*/
void OfflineTestProcessor::transitionInList(
const BF & aFF, TraceSequence & aTestPurpose, bool & flag)
{
if( aFF.is< ExecutionConfiguration >() )
{
ExecutionConfiguration * theEC = aFF.to_ptr< ExecutionConfiguration >();
if( theEC->hasCode() )
{
if( theEC->isTransition() )
{
if( aTestPurpose.containsObject(theEC->toTransition()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Transition found in TP !"
<< theEC->toTransition()->getAstNameID() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
flag = true;
}
//adding case where no test purpose is specified
//should not be used any more, treated in postprocess
/*
else if( aTestPurpose.points.empty() )
{
flag = true;
AVM_OS_WARN << "NB: The verdict was computed with no test purpose. " << std::endl;
}*/
}
}
}
else if( aFF.is< AvmCode >() )
{
const BFCode & theAC = aFF.bfCode();
BFCode newAC(theAC->getOperator());
BF bf;
for(AvmCode::iterator it = theAC->begin() ; it != theAC->end() ; ++it )
{
transitionInList((*it), aTestPurpose, flag);
}
}
}
bool OfflineTestProcessor::prefilter()
{
// ExecutionContext & delEC = NULL;
ecQueue = &( getExecutionQueue().getReadyQueue() );
ecQueueIt = ecQueue->begin();
ecQueueItEnd = ecQueue->end();
for( ; ecQueueIt != ecQueueItEnd ; )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << std::endl << std::endl << "Working with EC: "
<< (*ecQueueIt)->str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( not prefilter(* (*ecQueueIt)) )
{
AVM_OS_LOG << "OfflineTestProcessor::Prefilter won't continue here!"
<< std::endl;
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Erasing EC: " << (*ecQueueIt)->str_min() << std::endl
<< "\tIt's the " << (++theErasedNodes)
<< "'nth EC that has been deleted !" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// delEC = (*it);
ecQueueIt = ecQueue->erase(ecQueueIt);
// AbstractProcessorUnit::remove(delEC ,
// AVM_OS_LOG, "OfflineTestProcessor::remove");
}
else
{
ecQueueIt++;
}
}
return (getExecutionQueue().hasReady());
}
bool OfflineTestProcessor::hasIO(const BF & anElement)
{
if( anElement.invalid() )
{
return (false);
}
else if( anElement.is< AvmCode >() )
{
AvmCode * theAC = anElement.to_ptr< AvmCode >();
switch (theAC->getAvmOpCode()){
//case AVM_OPCODE_ASSIGN_NEWFRESH :
case AVM_OPCODE_INPUT:
case AVM_OPCODE_OUTPUT:
{
return true;
}default:
{
for(AvmCode::iterator it = theAC->begin();it != theAC->end();++it)
{
if( hasIO( (*it) ) )
{
return true;
}
}
return false;
}
}
}
else if( anElement.is< ExecutionConfiguration >() )
{
return (hasIO(anElement.to_ptr< ExecutionConfiguration >()->getCode()));
}
return false;
}
bool OfflineTestProcessor::portInObsSignals(const RuntimeID & runtimeCtx,
InstanceOfPort * port, AVM_OPCODE ioOpcode)
{
BFList::const_iterator itPoint = theObsSignals.points.begin();
BFList::const_iterator endPoint = theObsSignals.points.end();
TracePoint * aTracepoint;
for( ; itPoint != endPoint ; ++itPoint)
{
if( (*itPoint).is< TracePoint >() )
{
aTracepoint = (*itPoint).to_ptr< TracePoint >();
if( aTracepoint->isCom(ioOpcode, runtimeCtx, port) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Found, port in machine: " << aTracepoint->toString() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return true;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "NOT Found, port in machine (from tree): "
<< runtimeCtx.getQualifiedNameID() << " -> " << TracePoint::to_string(ioOpcode)
<< " port " << port->getQualifiedNameID() << std::endl;
AVM_OS_LOG << "NOT Found, comparing with (from obs signals): "
<< aTracepoint->toString() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
}
}
return false;
}
bool OfflineTestProcessor::portInCtrlSignals(TracePoint * portTP)
{
return( theTraceFilter.pass(portTP) );
}
bool OfflineTestProcessor::hasObservableSignal(
const BF & anElement)
{
if( anElement.invalid() )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "OfflineTestProcessor::hasObservableSignal:> "
"Invalid Trace, returning false !" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return (false);
}
else if( anElement.is< AvmCode >() )
{
AvmCode * theAC = anElement.to_ptr< AvmCode >();
for(AvmCode::iterator it = theAC->begin() ; it != theAC->end() ; ++it )
{
if( hasObservableSignal( (*it)) )
{
return true;
}
}
}
else if( anElement.is< ExecutionConfiguration >() )
{
return( hasObservableSignal(
anElement.to_ptr< ExecutionConfiguration >()->getCode(),
anElement.to_ptr< ExecutionConfiguration >()) );
}
return false;
}
bool OfflineTestProcessor::hasObservableSignal(
const BF & anElement, const ExecutionConfiguration * anExexConf)
{
if( anElement.invalid() )
{
return (false);
}
else if( anElement.is< AvmCode >() )
{
AvmCode * theAC = anElement.to_ptr< AvmCode >();
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PRE_FILTERING )
AVM_OS_LOG << "Analyzing I/O Element Trace "
<< anElement << "with AvmOpCode : "
<< TracePoint::to_string(theAC->getAvmOpCode()) << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PRE_FILTERING )
switch( theAC->getAvmOpCode() )
{
//case AVM_OPCODE_ASSIGN_NEWFRESH :
case AVM_OPCODE_INPUT:
{
// hardwired comparison
if( theAC->first().is< InstanceOfPort >() )
{
InstanceOfPort * ioPort = theAC->first().to_ptr< InstanceOfPort >();
if( ioPort->hasAliasTarget() )
{
ioPort = ioPort->getAliasTarget()->as< InstanceOfPort >();
}
if( portInObsSignals(
anExexConf->getRuntimeID(),
ioPort, AVM_OPCODE_INPUT) )
{
return true;
}
}
break;
}
case AVM_OPCODE_OUTPUT:
{
// hardwired comparison
if( theAC->first().is< InstanceOfPort >() )
{
InstanceOfPort * ioPort = theAC->first().to_ptr< InstanceOfPort >();
if( ioPort->hasAliasTarget() )
{
ioPort = ioPort->getAliasTarget()->as< InstanceOfPort >();
}
if( portInObsSignals(
anExexConf->getRuntimeID(),
ioPort, AVM_OPCODE_OUTPUT) )
{
return true;
}
}
break;
}
default:
{
AvmCode::iterator it = theAC->begin();
for( ; it != theAC->end() ; ++it )
{
if( hasObservableSignal((*it), anExexConf) )
{
return true;
}
}
return false;
}
}
return false;
}
return false;
}
bool OfflineTestProcessor::prefilter(ExecutionContext & anEC)
{
TraceSequence theLocalTrace;
OfflineTestProcessorInfo * currentOfflineTestInfo = NULL;
OfflineTestProcessorInfo * previousOfflineTestInfo = NULL;
if( anEC.hasPrevious() )
{
// Get "trace" (vector of pair of variable value), which is
// the one of its parent (previous)
if( anEC.getPrevious()->hasInformation() )
{
previousOfflineTestInfo = anEC.getPrevious()->getInformation()->
getUniqOfflineTestProcessorInfo();
theLocalTrace = previousOfflineTestInfo->getLocalTrace();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Its previous EC: " << anEC.getPrevious()->str_min() << std::endl;
printTrace( previousOfflineTestInfo->getLastObs() , "The (Last Obs) trace:", "\t" );
AVM_OS_LOG << "Its previous trace size is: "
<< previousOfflineTestInfo->getLocalTrace().points.size() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
else
{
previousOfflineTestInfo = anEC.getPrevious()
->getUniqInformation()->getUniqOfflineTestProcessorInfo();
}
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Warning in PROCESSOR Prefilter: node without previous? "
"Is it the Root ?" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
currentOfflineTestInfo = anEC.getUniqInformation()->getUniqOfflineTestProcessorInfo();
if( anEC.getHeight() <= 0 )
{
currentOfflineTestInfo->setLocalTrace(theTrace);
makeLocalObs(currentOfflineTestInfo->getLastObs(), theTrace);
// Setting time reference when system is timed
if(timedFlag)
{
const BF & referenceTimeVar = ENV.getRvalue(anEC.getAPExecutionData(),
anEC.refExecutionData().getSystemRID(),
timeReferenceInstance.to_ptr< InstanceOfData >());
anEC.getUniqInformation()->
getUniqOfflineTestProcessorInfo()->
setTimeReference(referenceTimeVar);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "1. Setting time reference to " << referenceTimeVar.str()
<< std::endl
<< "The Time Reference Instance is: " << timeReferenceInstance.str()
<< std::endl
<< currentOfflineTestInfo->getTimeReference().str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
if( anEC.hasRunnableElementTrace() )
{
currentOfflineTestInfo->setLastTransition(
anEC.getRunnableElementTrace());
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Root does have Runnable Element Trace! " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
else
{
currentOfflineTestInfo->setLastTransition(BF::REF_NULL);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Root does NOT have Runnable Element Trace! " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Root, assigning and skipping: " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
return true;
}
if( previousOfflineTestInfo->getTheAnalyzedMark() == true )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Verdict already computed!!!!!!!!!! for EC: "
<< anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
return false;
}
if( not hasObservableSignal(anEC.getIOElementTrace()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "jumping!!!!!!!! not interesting!!!!!!!! for EC: "
<< anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
if(timedFlag)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "setting reference of father in EC: "
<< anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
currentOfflineTestInfo->setTimeReference(
anEC.getPrevious()->getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getTimeReference());
}
if( theTrace.points.empty()
|| (not hasIO(anEC.getIOElementTrace()))
|| (previousOfflineTestInfo->getTheAnalyzedMark() == true)
|| (not hasObservableSignal(anEC.getIOElementTrace())) )
{
currentOfflineTestInfo->setLocalTrace(
previousOfflineTestInfo->getLocalTrace());
currentOfflineTestInfo->setLastObs(
previousOfflineTestInfo->getLastObs());
currentOfflineTestInfo->setLastTransition(
previousOfflineTestInfo->getLastTransition());
currentOfflineTestInfo->setTheAnalyzedMark(
previousOfflineTestInfo->getTheAnalyzedMark());
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Trace already read, or tau, or already failed/inconci, "
"or projecting,\nassigning and skipping EC: " << anEC.str_min()
<< std::endl
<< "Local Trace size : "
<< currentOfflineTestInfo->getLocalTrace().points.size()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
return true;
}
// the last observation is stored in the node (to find a match in the trace)
TraceSequence lastObs;
makeLocalObs(lastObs, theLocalTrace);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "The local trace is (assigned!): " << std::endl;
printTrace(theLocalTrace);
AVM_OS_COUT << "\nOfflineTestProcessor::prefilter(...) EC:> "
<< anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
if( AssignValuesIfObservable(anEC, theLocalTrace) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Something was read " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
// assign last obs (since something was read/localObs was modified)
currentOfflineTestInfo->setLastObs(lastObs);
currentOfflineTestInfo->setLastTransition(
anEC.getRunnableElementTrace());
// each EC has its own copy of the trace
currentOfflineTestInfo->setLocalTrace(theLocalTrace);
// checking trace length
if( currentOfflineTestInfo->getLocalTrace().points.empty() )
{
// the trace is finished for this path, set the flag to true so we don't
// continue calculating
currentOfflineTestInfo->setTheAnalyzedMark(true);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "The flag was set to true, this tree path should stop at EC: "
<< anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
}
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
AVM_OS_LOG << "Nothing was read in this EC: " << anEC.str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PRE_FILTERING )
// it was necessarily an input or an output that was not read, so we mark
// the entire path so we don't analyze it anymore (the verdict will be
// emitted later
currentOfflineTestInfo->setTheAnalyzedMark(true);
// assign last obs of parent (since nothing was read)
currentOfflineTestInfo->setLastObs(
previousOfflineTestInfo->getLastObs());
currentOfflineTestInfo->setLastTransition(
previousOfflineTestInfo->getLastTransition());
// each EC has its own copy of the trace
currentOfflineTestInfo->setLocalTrace(
previousOfflineTestInfo->getLocalTrace());
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// POST-FILTER API
////////////////////////////////////////////////////////////////////////////////
bool OfflineTestProcessor::postfilter()
{
ecQueue = &( getExecutionQueue().getResultQueue() );
ecQueueIt = ecQueue->begin();
ecQueueItEnd = ecQueue->end();
for( ; ecQueueIt != ecQueueItEnd ; )
{
if( not postfilter(* (*ecQueueIt)) )
{
AVM_OS_LOG << "FAIL in postfilter offline test!" << std::endl;
return false;
}
else
{
++ecQueueIt;
}
}
return (getExecutionQueue().hasResult());
}
bool OfflineTestProcessor::postfilter(ExecutionContext & anEC)
{
if( (anEC.getHeight() <= 0) || (theTrace.points.size() == 0) ||
(not hasIO(anEC.getIOElementTrace())) ||
(not hasObservableSignal(anEC.getIOElementTrace())) )
{
return true;
}
OfflineTestProcessorInfo * currentOfflineTestInfo =
anEC.getUniqInformation()->getUniqOfflineTestProcessorInfo();
// set THIS current time (since it is not a tau, nor it was projected)
// in case when the system is timed
if(timedFlag)
{
const BF & referenceTimeVar = ENV.getRvalue(
anEC.getAPExecutionData(),
anEC.refExecutionData().getSystemRID(),
timeReferenceInstance.to_ptr< InstanceOfData >() );
currentOfflineTestInfo->setTimeReference(referenceTimeVar);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "2. Setting time reference to "
<< referenceTimeVar.str()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << "The level nodes is now: " << std::endl;
// ListOfExecutionContext::iterator itl = theLevelNodes.begin();
// ListOfExecutionContext::iterator endItl = theLevelNodes.end();
// for( ; itl != endItl ; itl++)
// {
// AVM_OS_LOG << "EC: " << (*itl)->str_min() << std::endl;
// }
// AVM_OS_LOG << "CUrr height: " << anEC.getHeight() << std::endl;
// << "waiting top EC: " << getExecutionQueue().topWaiting()->str_min()
// << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
/*
// only if the next context to execute is in a new level of the tree, we
// examine what happened with all the nodes in the same level
if( not getExecutionQueue().hasWaiting() ||
getExecutionQueue().topWaiting()->getHeight() != anEC.getHeight() )
{
//we are in a new level:
// 1. update height
// 2. remove first obs from trace, keep it in lastObs
// 3. according to the set of localObs of all execution contexts of the
// previous height, give verdicts:
// 3.1 if there is at least one empty obs, it is because it was
// read/accepted by a node in the tree
// 3.1.1 if the node for which the obs is empty is in the path,
// if the trace is empty, incr PASS
// 3.1.2 if the node for which the obs is empty is not in the path,
// if the trace is empty, incr WeakPASS
// 3.2 if the trace is empty:
// 3.2.1 if PASS > 0 and WeakPASS > 0, emit WeakPASS
// 3.2.2 if PASS > 0 and WeakPASS == 0, emit PASS
// 3.2.3 if PASS == 0 and WeakPASS > 0, emit INCONCr
// 3.3 if there is no empty obs, it is because no node read/accepted the trace:
// 3.3.1 if lastObs is an input, emit INCONC?
// 3.3.2 if lastObs is an output or a delay, emit FAIL
// 3.4 if there is an obs and the trace is not empty, continue
// 4. clear the level nodes
// step 1
theHeight = anEC.getHeight();
// step 2
TraceOfObs lastObs;
makeLocalObs(lastObs, theTrace);
removeOneObs(theTrace);
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "ahora el size de la trace es " << theTrace.size() <<std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// step 3
// parcour all nodes in the list
ListOfExecutionContext::iterator itl = theLevelNodes.begin();
ListOfExecutionContext::iterator endItl = theLevelNodes.end();
int emptyObs = 0;
int weakPASS = 0;
int PASS = 0;
for( ; itl != endItl ; itl++)
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "verdict analizing EC: " << (*itl)->str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
bool flag = false;
transitionInTestPurpose(
(*itl)->getRunnableElementTrace(), theTestPurpose, flag);
const TraceOfObs & aLocalObs = (*itl)->getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getLocalObs();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "size of local obs is : " << aLocalObs.size() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( aLocalObs.empty() )
{
// it means this node accepted the head of the trace
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Size 0 for EC: " << (*itl)->str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
emptyObs++;
if( theTrace.size() == 0 )
{
// weakPASS or PAS
flag=false;
transitionInTestPurpose(
(*itl)->getRunnableElementTrace(), theTestPurpose, flag);
if( flag )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Found in test purpose, pass!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
PASS ++;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Not found in test pourpose, weakPass" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
weakPASS ++;
}
}
}
}
// we delete the first transition in the list, since we changed of
// level in the tree
if( not theTestPurpose.empty() )
{
theTestPurpose.erase(theTestPurpose.begin());
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "NOW The test purpose (sequence of transition names) is: "
<< std::endl;
for( VectorOfString::iterator i = theTestPurpose.begin() ;
i != theTestPurpose.end() ; ++i )
{
AVM_OS_LOG << *i << std::endl;
}
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else
{
AVM_OS_WARN << "Error: Test purpose is empty before expected! "
<< std::endl;
return false;
}
// step 3.2
if( theTrace.size() ==0 && emptyObs > 0 )
{
if( weakPASS > 0 )
{
if( PASS == 0 )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is InconcR!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "INTONCr";
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Weak Pass!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "weakPASS";
}
}
else if( PASS > 0 )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Pass!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "PASS";
}
}
// step 3.3
// if there is no empty obs, it is because no node read/accepted
// the trace:
// 3.2.1 if lastObs is an input, emit INCONC?
// 3.2.2 if lastObs is an output or a delay, emit FAIL
if( emptyObs == 0 )
{
if( lastObs.first().first().is< InstanceOfData >() &&
(theTimeVarInstance->getNameID() ==
lastObs.first().first().to_ptr< InstanceOfData >()->getNameID()) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Sense of observation is: "
<< lastObs.second().second().str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( lastObs.second().second().str() == "?" )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Inconc?" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "INCONC?";
}
else {
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Fail!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "FAIL";
}
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Sense of observation is: "
<< lastObs.first().second().str() <<std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( lastObs.first().second().str() == "?" )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Inconc? " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "INCONC?";
}
else {
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Fail! " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
verdictEmitted = true;
theVerdict = "FAIL";
}
}
}
// step 3.4
if( theTrace.size() > 0 && emptyObs > 0 )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Continue reading " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
VectorOfExecutionContext::iterator it = anEC.begin();
VectorOfExecutionContext::iterator endIt = anEC.end();
for( ; it != endIt ; ++it )
{
// noop??
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Nested noop " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
theLevelNodes.clear();
}
else
{www.npr.org/blogs/ed/2014/08/22/341898975/a-picture-of-language-the-fading-art-of-diagramming-sentences
// we are in the same level
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Not analyzing, out " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
*/
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "==> Rule: continue " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return( true );
}
////////////////////////////////////////////////////////////////////////////////
// POST-PROCESS API
////////////////////////////////////////////////////////////////////////////////
void OfflineTestProcessor::searchLeaves(const ExecutionContext & anEC)
{
if( anEC.isLeafNode() && anEC.isnotRoot() )
{
// it is a leaf, take its parent
// (the last leave is not evaluated by the filters)
if( not theLeavesECVector.contains(anEC.getPrevious()) )
{
theLeavesECVector.append( anEC.getPrevious() );
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "LEAF!!! local Trace size : "
<< anEC.getPrevious()->getUniqInformation()->
getUniqOfflineTestProcessorInfo()->getLocalTrace().points.size()
<< " => the EC: " << anEC.getPrevious()->str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
}
else
{
// recursive lookup
ExecutionContext::child_iterator it = anEC.begin();
for( ; it != anEC.end() ; ++it )
{
searchLeaves( * (*it) );
}
}
}
bool OfflineTestProcessor::postprocess()
{
AVM_OS_COUT << "OfflineTestProcessor::postprocess()" << std::endl;
AVM_OS_LOG << "OfflineTestProcessor::postprocess()" << std::endl;
theLeavesECVector.clear();
searchLeaves( getConfiguration().refFirstTrace() );
if( theLeavesECVector.empty() )
{
AVM_OS_LOG << "ZERO LEAVE :> FAILED !" << std::endl;
theVerdict = "FAILED";
return( true );
}
// list of execution contexts that will store the ones with the smallest traces
List< ExecutionContext * > smallestTraces;
smallestTraces.append(theLeavesECVector.first());
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "1. Smallest traces size :" << smallestTraces.size() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
VectorOfString repeatedTraces;
OfflineTestProcessorInfo * offlineTestInfo = NULL;
// aux var to find strings in lists
bool flag = false;
// check the local trace, last obs and last transition for every leaf
ListOfExecutionContext::iterator it = theLeavesECVector.begin();
ListOfExecutionContext::iterator endIt = theLeavesECVector.end();
for( ; it != endIt ; ++it )
{
offlineTestInfo = (*it)->getInformation()->getUniqOfflineTestProcessorInfo();
//theInformationVector.clear();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "For this leave EC: " << (*it)->str_min() << std::endl
<< "\tlast obs: " << std::endl;
//printTrace(offlineTestInfo->getLastObs());
if( offlineTestInfo->getLastTransition().valid() )
{
AVM_OS_LOG << "Last trans :" << std::endl
<< offlineTestInfo->getLastTransition().str()
<< std::endl;
AVM_OS_LOG << "Local trace size :" << std::endl
<< offlineTestInfo->getLocalTrace().points.size()
<< std::endl;
AVM_OS_LOG << "Local trace :" << std::endl;
}
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( offlineTestInfo->getLastTransition().valid() &&
(offlineTestInfo->getLocalTrace().points.size() <
smallestTraces.first()->getInformation()->
getUniqOfflineTestProcessorInfo()->getLocalTrace().points.size()) )
{
// we found a smaller trace: clear the list and initialize it with this EC
smallestTraces.clear();
smallestTraces.append((*it));
repeatedTraces.clear();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Is smallest!" << std::endl;
AVM_OS_LOG << offlineTestInfo->getTheAnalyzedMark() << std::endl;
if( offlineTestInfo->getTheAnalyzedMark() == true )
{
AVM_OS_LOG << "Is marked!" << std::endl;
}
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else if( (offlineTestInfo->getLocalTrace().points.size() ==
smallestTraces.first()->getInformation()->
getUniqOfflineTestProcessorInfo()->getLocalTrace().points.size())
&& offlineTestInfo->getLastTransition().valid() )
{
// we found another node/path accepting the trace
// we need to check if the transition is different that all the elements in the list...
flag = false;
// TODO: intelligent way to check for repeated transitions? is that possible?
// transitionInList((*it)->getInformation()->
// getUniqOfflineTestProcessorInfo()->getLastTransition(),
// repeatedTraces, flag);
if( flag == false )
{
// different path accepting the same trace
smallestTraces.append((*it));
repeatedTraces.push_back(offlineTestInfo->getLastTransition().str());
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Is repeated!!!!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
}
}
// now, smallestTraces is the list of smallest traces, let's emit a verdict
int PASS = 0, weakPASS = 0, INCONCi = 0, FAIL = 0;
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "2. Smallest traces size :" << smallestTraces.size() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// we go through the entire list...
endIt = smallestTraces.end();
for( it = smallestTraces.begin() ; it != endIt ; it++ )
{
offlineTestInfo = (*it)->getInformation()->getUniqOfflineTestProcessorInfo();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Smallest trace :" << std::endl;
printTrace(offlineTestInfo->getLocalTrace());
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( offlineTestInfo->getLocalTrace().points.size() == 0 )
{
bool flag = false;
// if no test purpose was specified, then PASS
if(theTestPurpose.points.empty())
{
AVM_OS_LOG << "NB: The verdict was computed with no test purpose. " << std::endl;
flag = true;
}
// else, is the last transition part of the test purpose ?
else{
transitionInList((*it)->getInformation()->
getUniqOfflineTestProcessorInfo()->getLastTransition(),
theTestPurpose, flag);
}
//is it a PASS, weakPASS or a INCONCr?
if( flag )
{
(*it)->getwFlags().addObjectiveAchievedTrace();
(*it)->addInfo(*this, INFO_OFFLINETEST_DATA_PASS);
PASS++;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Size is 0, but transition not in TP of the EC: "
<< (*it)->str_min() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
weakPASS++;
}
}
else
{
// retrieve the tracePoint of the first action in localTrace
// if aTracePoint is a controllable input, emit INCONC?
// if aTracePoint is an output or an uncontrollable input, emit FAIL
TracePoint * aTracePoint = offlineTestInfo->
getLocalTrace().points.first().to_ptr<TracePoint>();
if( aTracePoint->isTime()
&& offlineTestInfo->getLocalTrace().points.populated()
&& ( (theTimeVarInstance == aTracePoint->object)
/*|| (theTimeVarInstance->getNameID()
== aTracePoint->object->getNameID())*/ ) )
{
aTracePoint = offlineTestInfo->
getLocalTrace().points.second().to_ptr<TracePoint>();
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "(1) Direction of observation is: "
<< aTracePoint->to_string(aTracePoint->op) << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
if( (aTracePoint->op == AVM_OPCODE_INPUT_ENV) &&
portInCtrlSignals(aTracePoint) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Inconc? for the EC: " << (*it)->str_min()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
INCONCi++;
break;
}
else if( (aTracePoint->op == AVM_OPCODE_INPUT) &&
portInCtrlSignals(aTracePoint) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Inconc? for the EC: " << (*it)->str_min()
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
INCONCi++;
break;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Verdict is Fail! (output of the form d.a"
" --with a output or delay)" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
FAIL++;
break;
}
}
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "Counters: "
<< "PASS: " << PASS << std::endl
<< "WeakPASS: " << weakPASS << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// let's emit the verdict
if( PASS > 0 && weakPASS == 0 )
{
theVerdictKind = VERDICT_PASS_KIND;
theVerdict = " THE VERDICT IS : PASS ";
verdictEmitted = true;
}
else if( PASS > 0 && weakPASS > 0 )
{
theVerdictKind = VERDICT_WEAK_PASS_KIND;
theVerdict = " THE VERDICT IS : weakPASS ";
verdictEmitted = true;
}
else if( PASS == 0 && weakPASS > 0 )
{
theVerdictKind = VERDICT_INCONCr_KIND;
theVerdict = " THE VERDICT IS : INCONCr ";
verdictEmitted = true;
}
else if( INCONCi > 0 )
{
theVerdictKind = VERDICT_INCONCi_KIND;
theVerdict = " THE VERDICT IS : INCONCi ";
verdictEmitted = true;
}
else if( FAIL > 0 )
{
theVerdictKind = VERDICT_FAIL_KIND;
theVerdict = " THE VERDICT IS : FAIL ";
verdictEmitted = true;
}
else
{
theVerdictKind = VERDICT_ABORT_KIND;
}
if( verdictEmitted == true )
{
//AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
// AVM_OS_LOG << EMPHASIS(theVerdict, '=', 80);
//AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_WARN << "ERROR ! something went wrong, no verdict emitted! "
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
}
return true;
}
/**
* EXIT API
*/
bool OfflineTestProcessor::exitImpl()
{
// SET EXIT CODE
switch( theVerdictKind )
{
case VERDICT_PASS_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_PASS_CODE );
break;
}
case VERDICT_WEAK_PASS_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_WEAK_PASS_CODE );
break;
}
case VERDICT_INCONCr_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_INCONCLUIVE_R_CODE);
break;
}
case VERDICT_INCONCi_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_INCONCLUIVE_INPUT_CODE );
break;
}
case VERDICT_FAIL_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_FAIL_CODE );
break;
}
case VERDICT_ABORT_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_ABORT_CODE );
break;
}
case VERDICT_UNDEFINED_KIND:
{
avm_set_exit_code( AVM_EXIT_VERDICT_UNDEFINED_CODE );
break;
}
default:
{
avm_set_exit_code( AVM_EXIT_VERDICT_ABORT_CODE );
break;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// NON-REGRESSION TEST API
////////////////////////////////////////////////////////////////////////////////
void OfflineTestProcessor::tddRegressionReportImpl(OutStream & os)
{
os << TAB << "THE VERDICT IS : ";
switch( theVerdictKind )
{
case VERDICT_PASS_KIND:
{
os << "PASS";
break;
}
case VERDICT_WEAK_PASS_KIND:
{
os << "WEAK_PASS";
break;
}
case VERDICT_INCONCr_KIND:
{
os << "INCONCr";
break;
}
case VERDICT_INCONCi_KIND:
{
os << "INCONCi";
break;
}
case VERDICT_FAIL_KIND:
{
os << "FAIL";
break;
}
case VERDICT_ABORT_KIND:
{
os << "ABORT";
break;
}
case VERDICT_UNDEFINED_KIND:
{
os << "UNDEFINED";
break;
}
default:
{
os << "ABORT";
break;
}
}
os << EOL_FLUSH;
}
/**
* Info Serialization
*/
void OfflineTestProcessorInfo::toStream(OutStream & os) const
{
if( theLastObs.points.nonempty() )
{
os << TAB << "TABLE{" << EOL;
os << TAB << "}" << EOL_FLUSH;
}
}
void OfflineTestProcessorInfo::toFscn(OutStream & os) const
{
if( theLastObs.points.nonempty() )
{
os << TAB << "TABLE{" << EOL;
os << TAB << "}" << EOL_FLUSH;
}
}
} /* namespace sep */