#include "TestCases.h"
#include "MTParser.h"
#include <windows.h>
#include "MTParserExcepStrEng.h"
MTSTRING MTTestCases::longToS(long val)
{
MTCHAR str[20];
return MTLTOSTR(val, str, 10);
}
bool MTTestCases::test()
{
addTest(_T("1+2"), 3, true);
addTest(_T("1-2"), -1, true);
addTest(_T("1--2"), 3, true);
addTest(_T("2*3"), 6, true);
addTest(_T("4/2"), 2, true);
addTest(_T("2^3"), 8, true);
addTest(_T("10%3"), 1, true);
addTest(_T("avg(1,1-1+2,3,(2+2))"), 2.5, true);
addTest(_T("sum(1,2,3,2^2)"), 10, true);
addTest(_T("rand()*0"), 0, true); // function with no argument
addTest(_T("min(1,2,3)"), 1, true); // overloaded function
addTest(_T("x+y+sin(0)/2^3-40.9*2"), -81.8, true);
addTest(_T("min(sin(x),2)"), 0, true);
addTest(_T("max(100.98,101)"), 101, true);
addTest(_T("min(sin([x+1]),2)"), 0, true); // begin-end variable name delimiters
addTest(_T("[min](1,0)"), 0, false); // min is not a variable name
addTest(_T("min(sin(ali),2)"), 0, false); // undefined variable "ali"
addTest(_T("foo(sin(x),2)"), 0, false); // undefined function "foo"
// unary minus op
addTest(_T("-1"),-1, true);
addTest(_T("--1"), 1, true);
addTest(_T("---1"), -1, true);
addTest(_T("-(1)"), -1, true);
addTest(_T("-(1+2)"), -3, true);
addTest(_T("--(1)"), 1, true);
addTest(_T("1+-2"), -1, true);
addTest(_T("1+-(((1+2)))"), -2, true);
// brackets
addTest(_T("-(1)+3"), 2, true);
addTest(_T("(2+3"), 2, false); // missing closing bracket
addTest(_T("(2+3-(3/2)"), 2, false); // missing closing bracket
addTest(_T("3/2)"), 2, false); // missing opening bracket
addTest(_T("(1)-2"), -1, true);
addTest(_T("sin(((1-1)))"), 0, true); // tricky inside brackets
addTest(_T("-(((-2)))+3"), 5, true);
addTest(_T("avg((2),4)"), 3, true);
// argument separator
addTest(_T("avg(2,,2)"), 0, false); // useless ","
addTest(_T("avg(2,2,)"), 0, false); // useless "," at the end
addTest(_T("avg(,2,2)"), 0, false); // useless "," at the beginning
// bad syntax
addTest(_T("sin(1,2)"), 0, false); // too many arguments
addTest(_T("sin()"), 0, false); // not enough argument
addTest(_T("1+2/4+"), 0, false); // expression cannot end with an operator
addTest(_T("sin(+))"), 0, false); // missing + arguments
addTest(_T("sin(-)"), 0, false); // missing - arguments
addTest(_T("(2+3)2"), 0, false); // the * operator is not implicit
addTest(_T("5.1.2+3"), 0, false); // 5.1.2 is not a valid number
return runTest();
}
void MTTestCases::addTest(MTSTRING expr, MTDOUBLE result, bool valid)
{
TESTCASE tc;
tc.expr = expr;
tc.expectedResult = result;
tc.valid = valid;
m_testCases.push_back(tc);
}
bool MTTestCases::runTest()
{
MTParser parser;
int nbTests = m_testCases.size();
bool success = true;
MTDOUBLE x,y;
x=0;
y=0;
try
{
parser.defineVar(_T("x"), &x);
parser.defineVar(_T("x+1"), &x); // variable name with operator character: use begin-end delimiters
parser.defineVar(_T("y"), &y);
}
catch( MTException &e )
{
MTSTRING msg = _T("Unit test definition error: ");
msg += e.m_description;
msg += _T("\n\r");
OutputDebugString(msg.c_str());
return false;
}
int t;
for( t=0; t<nbTests; t++ )
{
try
{
MTDOUBLE val = parser.evaluate(m_testCases[t].expr.c_str());
if(!m_testCases[t].valid )
{
MTSTRING msg = _T("Test failed #");
msg += longToS(t);
msg += _T(", ");
msg += m_testCases[t].expr;
msg += _T(". Reason->expected failed");
msg += _T("\n\r");
OutputDebugString(msg.c_str());
success = false;
}
if( val != m_testCases[t].expectedResult )
{
MTSTRING msg = _T("Test failed #");
msg += longToS(t);
msg += _T(", ");
msg += m_testCases[t].expr;
msg += _T(". Reason->bad result");
msg += _T("\n\r");
OutputDebugString(msg.c_str());
success = false;
}
}
catch( MTException &e)
{
if( m_testCases[t].valid )
{
MTSTRING msg = _T("Test failed #");
msg += longToS(t);
msg += _T(", ");
msg += m_testCases[t].expr;
msg += _T(". Reason-> ");
msg += e.m_description;
msg += _T("\n\r");
OutputDebugString(msg.c_str());
success = false;
}
}
}
return success;
}