442 lines
12 KiB
C++
442 lines
12 KiB
C++
|
#include "srd-preproc-cmd-common.hh"
|
||
|
|
||
|
class SRDPreprocCmdFunctionsTest : public CppUnit::TestFixture
|
||
|
{
|
||
|
CPPUNIT_TEST_SUITE( SRDPreprocCmdFunctionsTest );
|
||
|
|
||
|
CPPUNIT_TEST( testBlessNoArgs );
|
||
|
CPPUNIT_TEST( testBlessMissing );
|
||
|
CPPUNIT_TEST( testBlessEmpty );
|
||
|
CPPUNIT_TEST( testBlessInvalid1 );
|
||
|
CPPUNIT_TEST( testBlessInvalid2 );
|
||
|
CPPUNIT_TEST( testBlessInvalid3 );
|
||
|
CPPUNIT_TEST( testBlessInvalid4 );
|
||
|
CPPUNIT_TEST( testBlessEmptyFunction );
|
||
|
CPPUNIT_TEST( testBlessFnWithArgs );
|
||
|
CPPUNIT_TEST( testBlessFnWithDupArgs );
|
||
|
CPPUNIT_TEST( testBlessFnWithOptArgs );
|
||
|
CPPUNIT_TEST( testBlessFnWithDupOptArgs );
|
||
|
CPPUNIT_TEST( testBlessFnWithOptArgsOnly );
|
||
|
CPPUNIT_TEST( testBlessFnWithDupArgsAll );
|
||
|
|
||
|
CPPUNIT_TEST( testCallNoArg );
|
||
|
CPPUNIT_TEST( testCallBlessedVar );
|
||
|
CPPUNIT_TEST( testCallBadArg );
|
||
|
CPPUNIT_TEST( testCallInvalidFunction );
|
||
|
CPPUNIT_TEST( testCallValidFunction );
|
||
|
CPPUNIT_TEST( testCallTooManyArgs );
|
||
|
CPPUNIT_TEST( testCallNotEnoughArgs );
|
||
|
CPPUNIT_TEST( testCallNotEnoughArgsOpt );
|
||
|
|
||
|
CPPUNIT_TEST( testBodyInnerList );
|
||
|
CPPUNIT_TEST( testDashFunction );
|
||
|
|
||
|
CPPUNIT_TEST( testBug00 );
|
||
|
CPPUNIT_TEST( testBug01 );
|
||
|
CPPUNIT_TEST( testBug02 );
|
||
|
CPPUNIT_TEST( testBug03 );
|
||
|
|
||
|
CPPUNIT_TEST_SUITE_END( );
|
||
|
|
||
|
public:
|
||
|
void testBlessNoArgs( );
|
||
|
void testBlessMissing( );
|
||
|
void testBlessEmpty( );
|
||
|
void testBlessInvalid1( );
|
||
|
void testBlessInvalid2( );
|
||
|
void testBlessInvalid3( );
|
||
|
void testBlessInvalid4( );
|
||
|
void testBlessEmptyFunction( );
|
||
|
void testBlessFnWithArgs( );
|
||
|
void testBlessFnWithDupArgs( );
|
||
|
void testBlessFnWithOptArgs( );
|
||
|
void testBlessFnWithDupOptArgs( );
|
||
|
void testBlessFnWithOptArgsOnly( );
|
||
|
void testBlessFnWithDupArgsAll( );
|
||
|
|
||
|
void testCallNoArg( );
|
||
|
void testCallBlessedVar( );
|
||
|
void testCallBadArg( );
|
||
|
void testCallInvalidFunction( );
|
||
|
void testCallValidFunction( );
|
||
|
void testCallTooManyArgs( );
|
||
|
void testCallNotEnoughArgs( );
|
||
|
void testCallNotEnoughArgsOpt( );
|
||
|
|
||
|
void testBodyInnerList( );
|
||
|
void testDashFunction( );
|
||
|
|
||
|
void testBug00( );
|
||
|
void testBug01( );
|
||
|
void testBug02( );
|
||
|
void testBug03( );
|
||
|
|
||
|
};
|
||
|
CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdFunctionsTest );
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessNoArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -bless )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessMissing( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -bless a ) " , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "unknown variable" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessEmpty( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a ) " ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 2 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 2 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "( )" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessInvalid1( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set x\n"
|
||
|
"nope\n"
|
||
|
")\n"
|
||
|
"( -bless x )\n"
|
||
|
"($x)" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 4 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 4 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "(nope)" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessInvalid2( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set x\n"
|
||
|
"()\n"
|
||
|
")\n"
|
||
|
"( -bless x )\n"
|
||
|
"($x)" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 4 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 4 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "(())" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessInvalid3( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set x\n"
|
||
|
"(nope)\n"
|
||
|
")\n"
|
||
|
"( -bless x )\n"
|
||
|
"($x)" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 4 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 4 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "((nope))" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessInvalid4( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set x\n"
|
||
|
"(()) nope\n"
|
||
|
")\n"
|
||
|
"( -bless x )\n"
|
||
|
"($x)" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 4 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 4 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "((()) nope)" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessEmptyFunction( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( ) x ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a ) " ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "x" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( u v w ) ( -raw $u $v $w ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a b c d ) " ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "b c d" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithDupArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( u v u ) ( -raw $u $v ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a b c d ) " ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 2 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 2 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "( ( ( u v u ) $u $v ) b c d )" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithOptArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( u ( v ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"($a b c d)\n"
|
||
|
"($a e)\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "( b ) ( c d ) ( e ) ( )" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithDupOptArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( u ( v v ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a b )" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 2 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 2 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "( ( ( u ( v v ) ) ( $u ) ( $v ) ) b )" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithOptArgsOnly( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( ( v ) ) ( -raw ( $v ) ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a ) ( $a b ) ( $a c d )" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "( ) ( b ) ( c d )" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBlessFnWithDupArgsAll( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set a ( ( u ( v u ) ) ( -raw ( $u ) ( $v ) ) ) )\n"
|
||
|
"( -bless a )\n"
|
||
|
"( $a b )" ,
|
||
|
errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "invalid function" , 2 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 2 , 10 );
|
||
|
CPPUNIT_ASSERT( check( "( ( ( u ( v u ) ) ( $u ) ( $v ) ) b )" , output ) );
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallNoArg( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 9 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallBlessedVar( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set f (() x))\n"
|
||
|
"(-bless f)\n"
|
||
|
"( -call $f )"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "x" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallBadArg( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call x )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "list expected" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 9 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallInvalidFunction( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call ( nope ) )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "list expected" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 11 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallValidFunction( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call ( -raw ( ( x ( y ) ) $y $x ) ) a b c )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "b c a" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallTooManyArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call ( -raw ( ( x ) $x ) ) a b )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "too many arguments" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 33 );
|
||
|
CPPUNIT_ASSERT( check( "a" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallNotEnoughArgs( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call ( -raw ( ( x ) $x ) ) )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 31 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testCallNotEnoughArgsOpt( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process( "( -call ( -raw ( ( x y ( z ) ) $x ) ) a )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
|
||
|
M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
|
||
|
M_CKERR_( 1 , "previous error cause" , 1 , 41 );
|
||
|
CPPUNIT_ASSERT( check( "" , output ) );
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBodyInnerList( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"( -set x (-raw ( () ) ) )\n"
|
||
|
"( -bless x )\n"
|
||
|
"( -call ( -raw ( () -not-a-command ) ) )\n"
|
||
|
"( -call ( -raw ( () $x ) ) )" , errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "-not-a-command (())" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testDashFunction( )
|
||
|
{
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set -f ((x) (-raw yo $x)))\n"
|
||
|
"(-bless -f)\n"
|
||
|
"(-f bob)\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "yo bob" , output ) );
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBug00( )
|
||
|
{
|
||
|
/* A bug with tail calls - the code below would output "y x" */
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set f1 ((-raw (a) $a)))\n"
|
||
|
"(-set f2 ((-raw (a) ($f1 $a))))\n"
|
||
|
"(-bless f1 f2)\n"
|
||
|
"($f2 x) y\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "x y" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBug01( )
|
||
|
{
|
||
|
/* Similar to bug 00, except with an ending parens. */
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set f1 ((-raw (a) $a)))\n"
|
||
|
"(-set f2 ((-raw (a) ($f1 $a))))\n"
|
||
|
"(-bless f1 f2)\n"
|
||
|
"(($f2 x))\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "(x)" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBug02( )
|
||
|
{
|
||
|
/* Causes a crash due to a missing location */
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set fn (-raw (((list))\n"
|
||
|
"(-set (first rest) $list)\n"
|
||
|
"(-if (-length ($first)) (\n"
|
||
|
"($first ($fn $rest))\n"
|
||
|
"))\n"
|
||
|
")))\n"
|
||
|
"(-bless fn)\n"
|
||
|
"($fn a b)\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "(a (b))" , output ) );
|
||
|
}
|
||
|
|
||
|
void SRDPreprocCmdFunctionsTest::testBug03( )
|
||
|
{
|
||
|
/* More tail-call problems (interaction between the "unswallow"
|
||
|
* part of the evaluator/function feeders and stuff that stands
|
||
|
* between them).
|
||
|
*/
|
||
|
T_SRDErrors errors;
|
||
|
T_SRDList output( process(
|
||
|
"(-set (f1 f2) (-raw\n"
|
||
|
"(() (-if 1 ()))\n"
|
||
|
"(() ($f1))\n"
|
||
|
"))\n"
|
||
|
"(-bless f1 f2)\n"
|
||
|
"(-eval ((-raw -eval) ((-raw $f2))))\n"
|
||
|
, errors ) );
|
||
|
CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
|
||
|
CPPUNIT_ASSERT( check( "(a (b))" , output ) );
|
||
|
}
|