trick/trick_source/sim_services/UnitTest/UnitTest.cpp
Jacqueline Deans 9c8799610f
Variable Server - var_send_once and integration test (#1330)
* Adds the send_once command and message type, which allows a user to request a variable to be sent immediately and only once (intended to replace the var_add, var_send, var_clear idiom that is commonly used for this purpose)
* Minor refactoring of variable server internals to reduce repeated code
* Adds SIM_test_varserv to integration test to test basic variable server functionality
* Changes graphics client for SIM_billiards to use var_send_once as an example of intended use
* Add documentation for var_send_once in docs and tutorial
* Set exit_code_enabled in trick unit tests to be true by default
* Patch for failing bookworm build
2022-08-18 10:47:07 -05:00

168 lines
5.4 KiB
C++

#include <iostream>
#include <fstream>
#include "trick/UnitTest.hh"
#include "trick/exec_proto.h"
#include "trick/message_proto.h"
#include "trick/message_type.h"
Trick::UnitTest * the_unit_test_output ;
Trick::TestCase::TestCase(std::string in_test_case_name , std::string in_failure_string) {
name = in_test_case_name ;
status = std::string("run") ;
elapsed_time = 0.0 ;
failure_string = in_failure_string ;
}
Trick::TestSuite::TestSuite() {
num_failures = 0 ;
}
int Trick::TestSuite::add_test_results(std::string in_test_case_name , std::string in_failure_string ) {
Trick::TestCase * new_test ;
new_test = new TestCase(in_test_case_name , in_failure_string) ;
test_results.push_back(new_test) ;
if ( in_failure_string.compare("") ) {
num_failures++ ;
}
return(0) ;
}
int Trick::TestSuite::add_test_requirements(std::string test_case , std::string par_num) {
unsigned int jj;
TestCase * curr_case ;
for (jj = 0 ; jj != test_results.size() ; jj++ ) {
curr_case = test_results[jj] ;
if (curr_case->name == test_case) {
curr_case->parent = par_num;
}
}
return(0);
}
void Trick::TestSuite::delete_test_results() {
std::vector <Trick::TestCase *>::iterator it ;
for ( it = test_results.begin() ; it != test_results.end() ; it++ ) {
delete (*it) ;
}
test_results.clear() ;
}
Trick::UnitTest::UnitTest() {
the_unit_test_output = this ;
enabled = false ;
exit_code_enabled = true ;
file_name = std::string("test_details.xml") ;
name = std::string("AllTests") ;
}
Trick::UnitTest::~UnitTest() {
std::map< std::string , TestSuite >::iterator it ;
for ( it = test_suites.begin() ; it != test_suites.end() ; it++ ) {
(it->second).delete_test_results() ;
}
}
int Trick::UnitTest::add_test_results(std::string in_test_suite_name , std::string in_test_case , std::string in_failure_string ) {
if ( enabled ) {
test_suites[in_test_suite_name].add_test_results(in_test_case , in_failure_string) ;
if ( in_failure_string.compare("") ) {
message_publish(MSG_ERROR, "[ FAILED ] %s:%s %s\n",
in_test_suite_name.c_str() , in_test_case.c_str() , in_failure_string.c_str()) ;
} else {
message_publish(MSG_NORMAL, "\033[32m[ OK ]\033[0m %s:%s\n", in_test_suite_name.c_str() , in_test_case.c_str() ) ;
}
}
return(0) ;
}
int Trick::UnitTest::add_test_requirements(std::string in_test_suite_name, std::string in_test_case, std::string par_num) {
if ( enabled ) {
test_suites[in_test_suite_name].add_test_requirements(in_test_case , par_num) ;
}
return 0 ;
}
bool Trick::UnitTest::enable() {
enabled = true ;
return(true) ;
}
int Trick::UnitTest::set_exit_code_enabled(bool in_enable) {
exit_code_enabled = in_enable ;
return 0 ;
}
int Trick::UnitTest::set_test_name(std::string in_name) {
name = in_name ;
return 0 ;
}
int Trick::UnitTest::set_file_name(std::string in_name) {
file_name = in_name ;
return 0 ;
}
int Trick::UnitTest::write_output() {
std::ofstream out ;
unsigned int num_tests = 0 ;
unsigned int num_failures = 0 ;
std::map< std::string , TestSuite >::iterator it ;
TestSuite * curr_suite ;
TestCase * curr_case ;
unsigned int jj ;
if ( enabled ) {
for ( it = test_suites.begin() ; it != test_suites.end() ; it++ ) {
curr_suite = &(it->second) ;
num_tests += curr_suite->test_results.size() ;
num_failures += curr_suite->num_failures ;
}
message_publish(MSG_NORMAL, "Total tests: %d , Failures: %d\n", num_tests , num_failures ) ;
out.open(file_name.c_str()) ;
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl ;
out << "<testsuites tests=\"" << num_tests << "\" failures=\"" << num_failures <<
"\" disabled=\"0\" errors=\"0\" time=\"0.0\" name=\"" << name << "\">" << std::endl ;
for ( it = test_suites.begin() ; it != test_suites.end() ; it++ ) {
curr_suite = &(it->second) ;
out << " <testsuite name=\"" << it->first << "\" tests=\"" << curr_suite->test_results.size() ;
out << "\" failures=\"" << num_failures << "\" disabled=\"0\" errors=\"0\" time=\"0.0\">" << std::endl ;
for ( jj = 0 ; jj < curr_suite->test_results.size() ; jj++ ) {
curr_case = curr_suite->test_results[jj] ;
out << " <testcase name=\"" << curr_case->name << "\" status=\"" << curr_case->status ;
out << "\" time=\"0\" classname=\"" << it->first << "\"" ;
// parent stuff goes here
//out << " parent=\"" << curr_case->parent << "\"" ;
if ( curr_case->failure_string.compare("") ) {
out << " >" << std::endl ;
out << " <failure message=\"" << curr_case->failure_string << "\" type=\"\"/>" << std::endl ;
out << " </testcase>" << std::endl;
} else {
out << " />" << std::endl ;
}
}
out << " </testsuite>" << std::endl ;
}
out << "</testsuites>" << std::endl ;
if ( exit_code_enabled && num_failures > 0 ) {
exec_terminate_with_return( 1 , __FILE__ , __LINE__ , "Unit Test failure detected." ) ;
}
}
return(0) ;
}