2014-09-05 14:39:24 +02:00
|
|
|
void program::test()
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
MIN_ARGUMENTS(1);
|
|
|
|
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
const string stack_size("-> stack size should be ");
|
|
|
|
const string stack_value("-> stack should be ");
|
|
|
|
const string cmd_error("-> error should be ");
|
|
|
|
const string cmd_exit("exit test");
|
2017-04-22 22:49:44 +02:00
|
|
|
|
|
|
|
string test_filename = ((ostring*)_stack->pop_back())->_value;
|
2015-05-19 17:51:03 +02:00
|
|
|
ifstream test_file(test_filename.c_str());
|
2017-04-22 22:49:44 +02:00
|
|
|
int tests = 0;
|
|
|
|
int tests_failed = 0;
|
|
|
|
int steps = 0;
|
|
|
|
int steps_failed = 0;
|
2014-09-05 14:39:24 +02:00
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
if (test_file.is_open())
|
|
|
|
{
|
|
|
|
string test_title;
|
|
|
|
string entry;
|
|
|
|
ret_value ret;
|
|
|
|
stack stk;
|
|
|
|
heap hp;
|
|
|
|
bool failed = false;
|
2017-04-22 22:49:44 +02:00
|
|
|
bool is_first_step;
|
|
|
|
bool is_test_error_shown;
|
2015-05-19 17:51:03 +02:00
|
|
|
int last_err;
|
|
|
|
stringstream cerr_buffer;
|
|
|
|
streambuf* cerr_old_buffer;
|
2014-09-05 14:39:24 +02:00
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// redirect cerr
|
|
|
|
cerr_old_buffer = cerr.rdbuf(cerr_buffer.rdbuf());
|
2014-09-05 14:39:24 +02:00
|
|
|
|
2017-04-22 22:49:44 +02:00
|
|
|
while (!test_file.eof())
|
2015-05-19 17:51:03 +02:00
|
|
|
{
|
|
|
|
getline(test_file, entry);
|
|
|
|
if (entry.substr(0,2)=="##")
|
|
|
|
{
|
|
|
|
cout << entry;
|
2017-04-22 22:49:44 +02:00
|
|
|
cout << endl;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
2017-04-23 15:37:42 +02:00
|
|
|
else if (entry.substr(0,2)=="# ")
|
2015-05-19 17:51:03 +02:00
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// indicates the status of previous test
|
|
|
|
if (failed == false && tests > 0)
|
|
|
|
cout<<FG_GREEN<<" PASSED"<<COLOR_OFF<<endl;
|
|
|
|
failed = false;
|
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// read a test title
|
|
|
|
test_title = entry;
|
2017-04-22 22:49:44 +02:00
|
|
|
is_first_step = true;
|
|
|
|
is_test_error_shown = false;
|
|
|
|
cout << test_title;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
2017-04-23 15:37:42 +02:00
|
|
|
// treat "-> stack size should be "
|
2015-05-19 17:51:03 +02:00
|
|
|
else if (entry.find(stack_size, 0) == 0)
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count test and step
|
|
|
|
if (is_first_step)
|
|
|
|
tests++;
|
|
|
|
steps++;
|
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// check current stack size
|
|
|
|
istringstream isub;
|
|
|
|
int size;
|
2014-09-05 14:39:24 +02:00
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
isub.str(entry.substr(stack_size.size()));
|
|
|
|
isub>>size;
|
|
|
|
if (size != (int)stk.size())
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count fail test and step
|
|
|
|
if (!is_test_error_shown)
|
|
|
|
{
|
|
|
|
cout<<FG_RED<<" FAIL"<<COLOR_OFF<<endl;
|
|
|
|
tests_failed++;
|
|
|
|
is_test_error_shown = true;
|
|
|
|
}
|
|
|
|
steps_failed++;
|
|
|
|
|
|
|
|
// show failure
|
|
|
|
cout<<"\t"<<entry<<endl;
|
|
|
|
cout<<"\tbut real stack size is "<<FG_RED<<stk.size()<<COLOR_OFF<<endl;
|
2015-05-19 17:51:03 +02:00
|
|
|
failed = true;
|
|
|
|
}
|
2017-04-22 22:49:44 +02:00
|
|
|
is_first_step = false;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
2017-04-23 15:37:42 +02:00
|
|
|
// treat "-> stack should be "
|
2015-05-19 17:51:03 +02:00
|
|
|
else if (entry.find(stack_value, 0) == 0)
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count test
|
|
|
|
if (is_first_step)
|
|
|
|
tests++;
|
|
|
|
steps++;
|
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// check current stack value
|
|
|
|
string stack_should_be = entry.substr(stack_value.size());
|
|
|
|
string stack_is;
|
|
|
|
string tmp;
|
2017-04-29 15:42:41 +02:00
|
|
|
for (int i = 0; i < (int)stk.size(); i++)
|
2015-05-19 17:51:03 +02:00
|
|
|
{
|
|
|
|
stringstream os;
|
2017-04-29 15:42:41 +02:00
|
|
|
if (i > 0)
|
2015-05-19 17:51:03 +02:00
|
|
|
stack_is += ", ";
|
|
|
|
((object*)stk.seq_obj(i))->show(os);
|
|
|
|
getline(os, tmp);
|
|
|
|
stack_is += tmp;
|
|
|
|
}
|
|
|
|
if (stack_is != stack_should_be)
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count fail test and step
|
|
|
|
if (!is_test_error_shown)
|
|
|
|
{
|
|
|
|
cout<<FG_RED<<" FAIL"<<COLOR_OFF<<endl;
|
|
|
|
tests_failed++;
|
|
|
|
is_test_error_shown = true;
|
|
|
|
}
|
|
|
|
steps_failed++;
|
|
|
|
|
|
|
|
// show failure
|
|
|
|
cout<<"\t"<<entry<<endl;
|
|
|
|
cout<<"\tbut real stack is "<<FG_RED<<stack_is<<COLOR_OFF<<endl;
|
2015-05-19 17:51:03 +02:00
|
|
|
failed = true;
|
|
|
|
}
|
2017-04-22 22:49:44 +02:00
|
|
|
is_first_step = false;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
2017-04-23 15:37:42 +02:00
|
|
|
// treat "-> error should be "
|
2015-05-19 17:51:03 +02:00
|
|
|
else if (entry.find(cmd_error, 0) == 0)
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count test
|
|
|
|
if (is_first_step)
|
|
|
|
tests++;
|
|
|
|
steps++;
|
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// check current error
|
|
|
|
istringstream isub;
|
|
|
|
int err_should_be;
|
|
|
|
isub.str(entry.substr(cmd_error.size()));
|
|
|
|
isub>>err_should_be;
|
|
|
|
if (err_should_be != last_err)
|
|
|
|
{
|
2017-04-22 22:49:44 +02:00
|
|
|
// count fail test and step
|
|
|
|
if (!is_test_error_shown)
|
|
|
|
{
|
|
|
|
cout<<FG_RED<<" FAIL"<<COLOR_OFF<<endl;
|
|
|
|
tests_failed++;
|
|
|
|
is_test_error_shown = true;
|
|
|
|
}
|
|
|
|
steps_failed++;
|
|
|
|
|
|
|
|
// show failure
|
|
|
|
cout<<"\t"<<entry<<endl;
|
|
|
|
cout<<"\tbut last error is "<<FG_RED<<last_err<<COLOR_OFF<<endl;
|
2015-05-19 17:51:03 +02:00
|
|
|
failed = true;
|
|
|
|
}
|
2017-04-22 22:49:44 +02:00
|
|
|
is_first_step = false;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
|
|
|
else if (entry.find(cmd_exit, 0) == 0)
|
|
|
|
{
|
|
|
|
// forced test end
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (entry.size() > 0)
|
|
|
|
{
|
|
|
|
// parse entry and run line
|
|
|
|
program prog;
|
2015-02-26 22:33:28 +01:00
|
|
|
ret = program::parse(entry.c_str(), prog);
|
2015-05-19 17:51:03 +02:00
|
|
|
if (ret == ret_ok)
|
|
|
|
{
|
|
|
|
// run it
|
|
|
|
(void)prog.run(stk, hp);
|
|
|
|
last_err = (int)prog.get_err();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-22 22:49:44 +02:00
|
|
|
|
|
|
|
// last test
|
|
|
|
// indicates the status of previous test
|
|
|
|
if (failed == false && tests > 0)
|
|
|
|
cout << FG_GREEN << " PASSED" << COLOR_OFF << endl;
|
2014-09-05 14:39:24 +02:00
|
|
|
|
2015-05-19 17:51:03 +02:00
|
|
|
// cerr back
|
|
|
|
cerr.rdbuf(cerr_old_buffer);
|
2017-04-22 22:49:44 +02:00
|
|
|
|
|
|
|
// conclusion
|
|
|
|
cout<<endl<<"Run "<<tests<<" tests: "<<tests-tests_failed<<" passed, ";
|
|
|
|
if(tests_failed>0)
|
|
|
|
cout<<FG_RED;
|
|
|
|
cout<<tests_failed<<" failed";
|
|
|
|
if(tests_failed>0)
|
|
|
|
cout<<COLOR_OFF;
|
|
|
|
|
|
|
|
cout<<" ("<<steps<<" steps: "<<steps-steps_failed<<" passed, ";
|
|
|
|
if(steps_failed>0)
|
|
|
|
cout<<FG_RED;
|
|
|
|
cout<<steps_failed<<" failed";
|
|
|
|
if(steps_failed>0)
|
|
|
|
cout<<COLOR_OFF;
|
|
|
|
cout<<")"<<endl;
|
2015-05-19 17:51:03 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
cerr << "test file '"<<test_filename<<"' not found" << endl;
|
2014-09-05 14:39:24 +02:00
|
|
|
}
|