qa: more tests for libeval_compiler

This commit is contained in:
Tomasz Wlostowski 2020-06-18 00:36:31 +02:00
parent 4e00ad9ca9
commit 6bddc4bdd6
2 changed files with 12 additions and 217 deletions

View File

@ -24,34 +24,16 @@
find_package(Boost COMPONENTS unit_test_framework REQUIRED) find_package(Boost COMPONENTS unit_test_framework REQUIRED)
find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED ) find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED )
find_program(LEMON lemon)
if( LEMON )
macro( generate_lemon_grammar TGT_NAME GRAMMAR_LEMON GRAMMAR_C )
add_custom_target( ${TGT_NAME}
DEPENDS ${GRAMMAR_LEMON}
COMMAND ${LEMON} -q ${GRAMMAR_LEMON}
COMMENT "Running Lemon on ${GRAMMAR_LEMON} -> ${GRAMMAR_C}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endmacro()
generate_lemon_grammar( libeval_grammar2 grammar.lemon grammar.c )
endif()
add_definitions(-DBOOST_TEST_DYN_LINK -DPCBNEW) add_definitions(-DBOOST_TEST_DYN_LINK -DPCBNEW)
if( BUILD_GITHUB_PLUGIN ) if( BUILD_GITHUB_PLUGIN )
set( GITHUB_PLUGIN_LIBRARIES github_plugin ) set( GITHUB_PLUGIN_LIBRARIES github_plugin )
endif() endif()
add_dependencies( pnsrouter pcbcommon pcad2kicadpcb libeval_grammar2 ${GITHUB_PLUGIN_LIBRARIES} ) add_dependencies( pnsrouter pcbcommon pcad2kicadpcb ${GITHUB_PLUGIN_LIBRARIES} )
add_executable( libeval_compiler_test add_executable( libeval_compiler_test
libeval_compiler_test.cpp libeval_compiler_test.cpp
libeval_compiler.cpp
../qa_utils/mocks.cpp ../qa_utils/mocks.cpp
../../common/base_units.cpp ../../common/base_units.cpp
../../3d-viewer/3d_viewer/3d_viewer_settings.cpp ../../3d-viewer/3d_viewer/3d_viewer_settings.cpp

View File

@ -3,8 +3,8 @@
#include "class_board.h" #include "class_board.h"
#include "class_track.h" #include "class_track.h"
#include "libeval_compiler.h"
#include <pcb_expr_evaluator.h>
#include <io_mgr.h> #include <io_mgr.h>
#include <kicad_plugin.h> #include <kicad_plugin.h>
@ -13,182 +13,6 @@
#include <profile.h> #include <profile.h>
class PCB_EXPR_VAR_REF;
class PCB_EXPR_UCODE : public LIBEVAL::UCODE
{
public:
virtual VAR_REF *createVarRef( const std::string &var, const std::string &field ) override;
void SetItems( BOARD_ITEM *a, BOARD_ITEM* b )
{
m_items[0] = a;
m_items[1] = b;
}
BOARD_ITEM *GetItem( int index ) const
{
return m_items[index];
}
private:
BOARD_ITEM *m_items[2];
};
class PCB_EXPR_VAR_REF : public LIBEVAL::UCODE::VAR_REF
{
public:
PCB_EXPR_VAR_REF ( int aItemIndex )
: m_itemIndex(aItemIndex)
{
//printf("*** createVarRef %p %d\n", this, aItemIndex );
}
void SetType( LIBEVAL::VAR_TYPE_T type )
{
m_type = type;
}
void AddAllowedClass ( TYPE_ID type_hash, PROPERTY_BASE *prop )
{
m_matchingTypes[type_hash] = prop;
}
virtual LIBEVAL::VAR_TYPE_T GetType( const LIBEVAL::UCODE* aUcode ) const override
{
return m_type;
}
virtual LIBEVAL::VALUE GetValue( const LIBEVAL::UCODE* aUcode ) const override
{
auto ucode = static_cast<const PCB_EXPR_UCODE*> (aUcode);
auto item = ucode->GetItem( m_itemIndex );
auto it = m_matchingTypes.find( TYPE_HASH( *item ) );
if( it == m_matchingTypes.end() )
{
printf("Null field!\n");
return LIBEVAL::VALUE(0.0);
}
else
{
if( m_type == LIBEVAL::VT_NUMERIC )
return LIBEVAL::VALUE( (double) item->Get<int>( it->second ) );
else
{
wxString str = item->Get<wxString>( it->second );
//printf("item %p GetStr '%s'\n", item, (const char*) str.c_str());
return LIBEVAL::VALUE( (const char*) str.c_str() );
}
}
}
private:
std::unordered_map<TYPE_ID, PROPERTY_BASE*> m_matchingTypes;
int m_itemIndex;
LIBEVAL::VAR_TYPE_T m_type;
};
LIBEVAL::UCODE::VAR_REF *PCB_EXPR_UCODE::createVarRef( const std::string &var, const std::string &field )
{
PCB_EXPR_VAR_REF *rv;
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
auto classes = propMgr.GetAllClasses();
auto vref = new PCB_EXPR_VAR_REF( var == "A" ? 0 : 1 );
for ( auto cls : classes )
{
if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) )
{
PROPERTY_BASE* prop = propMgr.GetProperty( cls.type, field );
if( prop )
{
//printf("Field '%s' class %s ptr %p\n", field.c_str(), (const char *) cls.name.c_str(), prop );
vref->AddAllowedClass( cls.type, prop );
if ( prop->TypeHash() == TYPE_HASH(int) )
vref->SetType( LIBEVAL::VT_NUMERIC );
else if ( prop->TypeHash() == TYPE_HASH(wxString) )
vref->SetType( LIBEVAL::VT_STRING );
else {
printf("Unknown property type\n");
}
}
}
}
return vref;
}
BOARD* loadBoard( const std::string& filename )
{
PLUGIN::RELEASER pi( new PCB_IO );
BOARD* brd = nullptr;
try
{
brd = pi->Load( wxString( filename.c_str() ), NULL, NULL );
}
catch( const IO_ERROR& ioe )
{
wxString msg = wxString::Format( _( "Error loading board.\n%s" ),
ioe.Problem() );
printf( "%s\n", (const char*) msg.mb_str() );
return nullptr;
}
return brd;
}
class PCB_UNIT_RESOLVER : public LIBEVAL::UNIT_RESOLVER
{
public:
virtual ~PCB_UNIT_RESOLVER()
{
}
virtual const std::vector<std::string>& GetSupportedUnits() const override
{
static const std::vector<std::string> pcbUnits = {"mil", "mm", "in"};
return pcbUnits;
}
virtual double Convert( const std::string aString, int unitId ) const override
{
double v = atof(aString.c_str());
switch(unitId)
{
case 0 :
return Mils2iu( v );
case 1:
return Millimeter2iu( v );
case 2:
return Mils2iu( v * 1000.0 );
default:
return v;
}
};
};
class PCB_EXPR_COMPILER : public LIBEVAL::COMPILER
{
public:
PCB_EXPR_COMPILER()
{
m_unitResolver.reset( new PCB_UNIT_RESOLVER );
}
};
bool testEvalExpr( const std::string expr, LIBEVAL::VALUE expectedResult, bool expectError = false, BOARD_ITEM* itemA = nullptr, BOARD_ITEM* itemB = nullptr ) bool testEvalExpr( const std::string expr, LIBEVAL::VALUE expectedResult, bool expectError = false, BOARD_ITEM* itemA = nullptr, BOARD_ITEM* itemB = nullptr )
{ {
PCB_EXPR_COMPILER compiler; PCB_EXPR_COMPILER compiler;
@ -207,7 +31,7 @@ bool testEvalExpr( const std::string expr, LIBEVAL::VALUE expectedResult, bool e
ok = true; ok = true;
return ok; return ok;
} else { } else {
printf("result: FAIL (unexpected parse error)\n"); printf("result: FAIL: %s\n", compiler.GetErrorStatus().Format().c_str() );
ok = false; ok = false;
} }
} }
@ -244,24 +68,6 @@ bool EvaluatePCBExpression( const std::string& aExpr, int& aResult )
return true; return true;
} }
class PCB_EXPR_EVALUATOR
{
public:
PCB_EXPR_EVALUATOR();
~PCB_EXPR_EVALUATOR();
bool Evaluate( const wxString& aExpr );
int Result() const { return m_result; }
wxString GetErrorString();
private:
bool m_error;
int m_result;
PCB_EXPR_COMPILER m_compiler;
PCB_EXPR_UCODE m_ucode;
}
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
{ {
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
@ -307,18 +113,25 @@ int main( int argc, char *argv[] )
trackA.SetNet( net1info ); trackA.SetNet( net1info );
trackB.SetNet( net2info ); trackB.SetNet( net2info );
trackB.SetLayer( F_Cu );
trackA.SetWidth( Mils2iu( 10 )); trackA.SetWidth( Mils2iu( 10 ));
trackB.SetWidth( Mils2iu( 20 )); trackB.SetWidth( Mils2iu( 20 ));
printf("TrkA %p netclass '%s'\n", &trackA, (const char*) trackA.GetNetClassName().c_str() ); printf("TrkA %p netclass '%s'\n", &trackA, (const char*) trackA.GetNetClassName().c_str() );
printf("TrkB %p netclass '%s'\n", &trackB, (const char*) trackB.GetNetClassName().c_str() ); printf("TrkB %p netclass '%s'\n", &trackB, (const char*) trackB.GetNetClassName().c_str() );
// testEvalExpr( "A.onlayer(\"F.Cu\") || A.onlayer(\"B.Cu\")", VAL(1.0), false, &trackA, &trackB );
testEvalExpr( "A.type == \"Pad\" && B.type == \"Pad\" && (A.onLayer(\"F.Cu\"))",VAL(0.0), false, &trackA, &trackB );
return 0;
testEvalExpr( "A.Width > B.Width", VAL(0.0), false, &trackA, &trackB ); testEvalExpr( "A.Width > B.Width", VAL(0.0), false, &trackA, &trackB );
testEvalExpr( "A.Width + B.Width", VAL(Mils2iu(10) + Mils2iu(20)), false, &trackA, &trackB ); testEvalExpr( "A.Width + B.Width", VAL(Mils2iu(10) + Mils2iu(20)), false, &trackA, &trackB );
testEvalExpr( "A.Netclass", VAL( (const char*) trackA.GetNetClassName().c_str() ), false, &trackA, &trackB ); testEvalExpr( "A.Netclass", VAL( (const char*) trackA.GetNetClassName().c_str() ), false, &trackA, &trackB );
testEvalExpr( "A.Netclass == \"HV\" && B.netclass == \"otherClass\"", VAL( 1.0 ), false, &trackA, &trackB ); testEvalExpr( "(A.Netclass == \"HV\") && (B.netclass == \"otherClass\") && (B.netclass != \"F.Cu\")", VAL( 1.0 ), false, &trackA, &trackB );
testEvalExpr( "A.Netclass + 1.0", VAL( 1.0 ), false, &trackA, &trackB ); testEvalExpr( "A.Netclass + 1.0", VAL( 1.0 ), false, &trackA, &trackB );
testEvalExpr( "A.type == \"Track\" && B.type == \"Track\" && A.layer == \"F.Cu\"", VAL(0.0), false, &trackA, &trackB );
testEvalExpr( "(A.type == \"Track\") && (B.type == \"Track\") && (A.layer == \"F.Cu\")", VAL(0.0), false, &trackA, &trackB );
return 0; return 0;
} }