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