#include "srd-preproc-cmd-common.hh"


class SRDPreprocCmdArithmeticTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE( SRDPreprocCmdArithmeticTest );

	CPPUNIT_TEST( testAddNoArgs );
	CPPUNIT_TEST( testAddOneArg );
	CPPUNIT_TEST( testAddIntInt );
	CPPUNIT_TEST( testAddIntLong );
	CPPUNIT_TEST( testAddLongInt );
	CPPUNIT_TEST( testAddLongLong );
	CPPUNIT_TEST( testAddIntFloat );
	CPPUNIT_TEST( testAddLongFloat );
	CPPUNIT_TEST( testAddFloatInt );
	CPPUNIT_TEST( testAddFloatLong );
	CPPUNIT_TEST( testAddFloatFloat );
	CPPUNIT_TEST( testAddManyInt );
	CPPUNIT_TEST( testAddManyFloat );
	CPPUNIT_TEST( testAddManyWithError );

	CPPUNIT_TEST( testSubNoArgs );
	CPPUNIT_TEST( testSubOneArg );
	CPPUNIT_TEST( testSubIntInt );
	CPPUNIT_TEST( testSubIntLong );
	CPPUNIT_TEST( testSubLongInt );
	CPPUNIT_TEST( testSubLongLong );
	CPPUNIT_TEST( testSubIntFloat );
	CPPUNIT_TEST( testSubLongFloat );
	CPPUNIT_TEST( testSubFloatInt );
	CPPUNIT_TEST( testSubFloatLong );
	CPPUNIT_TEST( testSubFloatFloat );
	CPPUNIT_TEST( testSubManyInt );
	CPPUNIT_TEST( testSubManyFloat );
	CPPUNIT_TEST( testSubManyWithError );

	CPPUNIT_TEST( testMulNoArgs );
	CPPUNIT_TEST( testMulOneArg );
	CPPUNIT_TEST( testMulIntInt );
	CPPUNIT_TEST( testMulIntLong );
	CPPUNIT_TEST( testMulLongInt );
	CPPUNIT_TEST( testMulLongLong );
	CPPUNIT_TEST( testMulIntFloat );
	CPPUNIT_TEST( testMulLongFloat );
	CPPUNIT_TEST( testMulFloatInt );
	CPPUNIT_TEST( testMulFloatLong );
	CPPUNIT_TEST( testMulFloatFloat );
	CPPUNIT_TEST( testMulManyInt );
	CPPUNIT_TEST( testMulManyFloat );
	CPPUNIT_TEST( testMulManyWithError );

	CPPUNIT_TEST( testDivNoArgs );
	CPPUNIT_TEST( testDivOneArg );
	CPPUNIT_TEST( testDivIntInt );
	CPPUNIT_TEST( testDivIntLong );
	CPPUNIT_TEST( testDivLongInt );
	CPPUNIT_TEST( testDivLongLong );
	CPPUNIT_TEST( testDivIntFloat );
	CPPUNIT_TEST( testDivLongFloat );
	CPPUNIT_TEST( testDivFloatInt );
	CPPUNIT_TEST( testDivFloatLong );
	CPPUNIT_TEST( testDivFloatFloat );
	CPPUNIT_TEST( testDivIntZero );
	CPPUNIT_TEST( testDivFloatZero );
	CPPUNIT_TEST( testDivManyInt );
	CPPUNIT_TEST( testDivManyFloat );
	CPPUNIT_TEST( testDivManyWithError );

	CPPUNIT_TEST( testModNoArgs );
	CPPUNIT_TEST( testModOneArg );
	CPPUNIT_TEST( testModIntInt );
	CPPUNIT_TEST( testModIntLong );
	CPPUNIT_TEST( testModLongInt );
	CPPUNIT_TEST( testModLongLong );
	CPPUNIT_TEST( testModIntFloat );
	CPPUNIT_TEST( testModLongFloat );
	CPPUNIT_TEST( testModFloatInt );
	CPPUNIT_TEST( testModFloatLong );
	CPPUNIT_TEST( testModFloatFloat );
	CPPUNIT_TEST( testModIntZero );
	CPPUNIT_TEST( testModFloatZero );
	CPPUNIT_TEST( testModManyInt );
	CPPUNIT_TEST( testModManyFloat );
	CPPUNIT_TEST( testModManyWithError );

	CPPUNIT_TEST( testNegNoArgs );
	CPPUNIT_TEST( testNegTooManyArgs );
	CPPUNIT_TEST( testNegBadArg );
	CPPUNIT_TEST( testNegInt );
	CPPUNIT_TEST( testNegLong );
	CPPUNIT_TEST( testNegReal );

	CPPUNIT_TEST_SUITE_END( );

   public:
	void testAddNoArgs( );
	void testAddOneArg( );
	void testAddIntInt( );
	void testAddIntLong( );
	void testAddLongInt( );
	void testAddLongLong( );
	void testAddIntFloat( );
	void testAddLongFloat( );
	void testAddFloatInt( );
	void testAddFloatLong( );
	void testAddFloatFloat( );
	void testAddManyInt( );
	void testAddManyFloat( );
	void testAddManyWithError( );

	void testSubNoArgs( );
	void testSubOneArg( );
	void testSubIntInt( );
	void testSubIntLong( );
	void testSubLongInt( );
	void testSubLongLong( );
	void testSubIntFloat( );
	void testSubLongFloat( );
	void testSubFloatInt( );
	void testSubFloatLong( );
	void testSubFloatFloat( );
	void testSubManyInt( );
	void testSubManyFloat( );
	void testSubManyWithError( );

	void testMulNoArgs( );
	void testMulOneArg( );
	void testMulIntInt( );
	void testMulIntLong( );
	void testMulLongInt( );
	void testMulLongLong( );
	void testMulIntFloat( );
	void testMulLongFloat( );
	void testMulFloatInt( );
	void testMulFloatLong( );
	void testMulFloatFloat( );
	void testMulManyInt( );
	void testMulManyFloat( );
	void testMulManyWithError( );

	void testDivNoArgs( );
	void testDivOneArg( );
	void testDivIntInt( );
	void testDivIntLong( );
	void testDivLongInt( );
	void testDivLongLong( );
	void testDivIntFloat( );
	void testDivLongFloat( );
	void testDivFloatInt( );
	void testDivFloatLong( );
	void testDivFloatFloat( );
	void testDivIntZero( );
	void testDivFloatZero( );
	void testDivManyInt( );
	void testDivManyFloat( );
	void testDivManyWithError( );

	void testModNoArgs( );
	void testModOneArg( );
	void testModIntInt( );
	void testModIntLong( );
	void testModLongInt( );
	void testModLongLong( );
	void testModIntFloat( );
	void testModLongFloat( );
	void testModFloatInt( );
	void testModFloatLong( );
	void testModFloatFloat( );
	void testModIntZero( );
	void testModFloatZero( );
	void testModManyInt( );
	void testModManyFloat( );
	void testModManyWithError( );

	void testNegNoArgs( );
	void testNegTooManyArgs( );
	void testNegBadArg( );
	void testNegInt( );
	void testNegLong( );
	void testNegReal( );
};
CPPUNIT_TEST_SUITE_REGISTRATION( SRDPreprocCmdArithmeticTest );

/*----------------------------------------------------------------------------*/

#define M_MKTEST_( OP , A1 , A2 ) \
	"( -set out ( -" OP " " A1 " " A2 " ) )\n" \
	"( -type-of $out )\n" \
	"( -if ( -eq ( -type-of $out ) long ) ( (-to-best-integer $out) ) ($out) )"

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testAddNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -add )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddOneArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -add 1 )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddIntInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "1" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 2" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddIntLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "1" , "12123456789" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddLongInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "12123456789" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddLongLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "12123456789" , "( -to-long 1 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12123456790" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddIntFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "1" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddLongFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , "( -to-long 1 )" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddFloatInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddFloatLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "( -to-long 1 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddFloatFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "add" , ".5" , "1.5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 2.0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddManyInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -add 1 2 3 4 5 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "15" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddManyFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -add 1 .5 .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "1.75" , output ) );
}

void SRDPreprocCmdArithmeticTest::testAddManyWithError( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -add 1 ( ) .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( "1.25" , output ) );
}

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testSubNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -sub )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubOneArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -sub 1 )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubIntInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "1" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubIntLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "1" , "12123456789" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long -12123456788" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubLongInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "12123456789" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12123456788" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubLongLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "12123456789" , "( -to-long 1 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12123456788" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubIntFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "1" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubLongFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , "( -to-long 1 )" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubFloatInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "1" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real -.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubFloatLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "( -to-long 1 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real -.5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubFloatFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "sub" , ".5" , "1.5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real -1.0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubManyInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -sub 20 1 2 3 4 5 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubManyFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -sub 1 .5 .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( ".25" , output ) );
}

void SRDPreprocCmdArithmeticTest::testSubManyWithError( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -sub 1 ( ) .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( ".75" , output ) );
}

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testMulNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mul )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulOneArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mul 1 )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulIntInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "2" , "3" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 6" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulIntLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "2" , "6000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulLongInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "6000000000" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulLongLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "6000000000" , "( -to-long 2 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 12000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulIntFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "2" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulLongFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , "( -to-long 2 )" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulFloatInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulFloatLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "( -to-long 2 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulFloatFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mul" , ".5" , "1.5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .75" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulManyInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mul 2 3 4 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "24" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulManyFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mul 2. .5 .1 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( ".1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testMulManyWithError( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mul 2 ( ) .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( ".5" , output ) );
}

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testDivNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivOneArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 1 )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivIntInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "4" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 2" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivIntLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "200" , "( -to-long 10 )" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 20" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivLongInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "12000000000" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 6000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivLongLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "12000000000" , "6000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 2" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivIntFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "2" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 4." , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivLongFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "6000000000" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 12e9" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivFloatInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , ".5" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .25" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivFloatLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "12e9" , "6000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 2." , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivFloatFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "div" , "1.5" , ".5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 3." , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivIntZero( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 10 0 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
	CPPUNIT_ASSERT( check( "10" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivFloatZero( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 2. 0. )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
	CPPUNIT_ASSERT( check( "2." , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivManyInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 20 2 5 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "2" , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivManyFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 2. .5 4. )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testDivManyWithError( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -div 2 ( ) .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( "8." , output ) );
}

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testModNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModOneArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 1 )" , errors ) );
	CPPUNIT_ASSERT_EQUAL( 0u , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModIntInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "4" , "3" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModIntLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "20" , "6000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 20" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModLongInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "6000000000" , "7" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "int 1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModLongLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "12000000000" , "7000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "long 5000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModIntFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "2" , "1.5" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .5" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModLongFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "6000000000" , "1e10" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 6e9" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModFloatInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "3.0" , "2" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 1." , output ) );
}

void SRDPreprocCmdArithmeticTest::testModFloatLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "12e9" , "7000000000" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real 5e9" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModFloatFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( M_MKTEST_( "mod" , "1.5" , ".6" )  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "real .3" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModIntZero( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 10 0 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
	CPPUNIT_ASSERT( check( "10" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModFloatZero( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 2. 0. )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "non-zero argument expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 11 );
	CPPUNIT_ASSERT( check( "2." , output ) );
}

void SRDPreprocCmdArithmeticTest::testModManyInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 23 5 2 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModManyFloat( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 2. .6 .15 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( ".05" , output ) );
}

void SRDPreprocCmdArithmeticTest::testModManyWithError( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -mod 2 ( ) .25 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real number expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( "0." , output ) );
}

/*----------------------------------------------------------------------------*/

void SRDPreprocCmdArithmeticTest::testNegNoArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg )"  , errors ) );
	CPPUNIT_ASSERT( check( "0" , output ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "not enough arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
}

void SRDPreprocCmdArithmeticTest::testNegTooManyArgs( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg 1 2 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "too many arguments" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 10 );
	CPPUNIT_ASSERT( check( "-1" , output ) );
}

void SRDPreprocCmdArithmeticTest::testNegBadArg( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg nope )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( 2u , errors.size( ) );
	M_CKERR_( 0 , "integer or real argument expected" , 1 , 3 );
	M_CKERR_( 1 , "previous error cause" , 1 , 8 );
	CPPUNIT_ASSERT( check( "0" , output ) );
}

void SRDPreprocCmdArithmeticTest::testNegInt( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg 12 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "-12" , output ) );
}

void SRDPreprocCmdArithmeticTest::testNegLong( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg 12000000000 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "-12000000000" , output ) );
}

void SRDPreprocCmdArithmeticTest::testNegReal( )
{
	T_SRDErrors errors;
	T_SRDList output( process( "( -neg -1.2 )"  , errors ) );
	CPPUNIT_ASSERT_EQUAL( uint32_t( 0 ) , errors.size( ) );
	CPPUNIT_ASSERT( check( "1.2" , output ) );
}