corelib/tests/srd-preproc-cmd-functions.cc

441 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 ) );
}