35 #ifndef OPENMS_CONCEPT_CLASSTEST_H 36 #define OPENMS_CONCEPT_CLASSTEST_H 48 #include <OpenMS/OpenMSConfig.h> 49 #include <OpenMS/config.h> 66 #define std__cout std::cout 82 validate(
const std::vector<std::string>& file_names);
85 std::string OPENMS_DLLAPI
89 inline bool OPENMS_DLLAPI
96 inline bool OPENMS_DLLAPI
103 inline bool OPENMS_DLLAPI
110 inline bool OPENMS_DLLAPI
117 template <
typename T>
131 const char* number_1_stringified,
132 bool number_1_is_realtype,
Int number_1_written_digits,
133 long double number_2,
const char* number_2_stringified,
134 bool ,
Int number_2_written_digits);
149 const std::string& string_1,
150 const char* string_1_stringified,
151 const std::string& string_2,
152 const char* string_2_stringified);
157 const std::string& string_1,
158 const char* string_1_stringified,
159 const std::string& string_2,
160 const char* string_2_stringified);
169 const std::string& filename_2);
182 const std::string& whitelist);
191 extern OPENMS_DLLAPI
double ratio;
200 extern OPENMS_DLLAPI
double absdiff;
206 extern OPENMS_DLLAPI
int verbose;
212 extern OPENMS_DLLAPI
bool test;
227 extern OPENMS_DLLAPI std::string
test_name;
245 extern OPENMS_DLLAPI std::ifstream
infile;
269 extern OPENMS_DLLAPI
bool newline;
271 template <
typename T1,
typename T2>
273 testEqual(
const char* ,
int line,
const T1& expression_1,
274 const char* expression_1_stringified,
275 const T2& expression_2,
276 const char* expression_2_stringified)
280 this_test = bool(expression_1 == T1(expression_2));
286 std__cout <<
" + line " << line <<
": TEST_EQUAL(" 287 << expression_1_stringified <<
',' 288 << expression_2_stringified <<
"): got " << expression_1
289 <<
", expected " << expression_2 << std::endl;
293 std__cout <<
" - line " << line <<
": TEST_EQUAL(" 294 << expression_1_stringified <<
',' 295 << expression_2_stringified <<
"): got " << expression_1
296 <<
", expected " << expression_2 << std::endl;
297 failed_lines_list.push_back(line);
302 template <
typename T1,
typename T2>
305 const char* expression_1_stringified,
306 const T2& expression_2,
307 const char* expression_2_stringified)
311 this_test = !(expression_1 == T1(expression_2));
317 std__cout <<
" + line " << line <<
": TEST_NOT_EQUAL(" 318 << expression_1_stringified <<
',' 319 << expression_2_stringified <<
"): got " << expression_1
320 <<
", forbidden is " << expression_2 << std::endl;
324 std__cout <<
" - line " << line <<
": TEST_NOT_EQUAL(" 325 << expression_1_stringified <<
',' 326 << expression_2_stringified <<
"): got " << expression_1
327 <<
", forbidden is " << expression_2 << std::endl;
328 failed_lines_list.push_back(line);
393 #define START_TEST(class_name, version) \ 394 int main(int argc, char** argv) \ 396 OpenMS::UInt64 seed = 2453440375; \ 397 OpenMS::UniqueIdGenerator::setSeed(seed); \ 398 TEST::version_string = version; \ 403 << "This is " << argv[0] << ", the test program for the\n" \ 404 << # class_name " class.\n" \ 406 "On successful operation it returns PASSED,\n" \ 407 "otherwise FAILED is printed.\n"; \ 427 catch (::OpenMS::Exception::BaseException& e) \ 429 TEST::this_test = false; \ 430 TEST::test = false; \ 431 TEST::all_tests = false; \ 433 TEST::initialNewline(); \ 434 std__cout << "Error: Caught unexpected OpenMS exception of type '" \ 437 if ((e.getLine() > 0) && (std::strcmp(e.getFile(), "") != 0)) \ 439 std__cout << " thrown in line " << e.getLine() << " of file '" << e.getFile() \ 440 << "' in function '" << e.getFunction() << "'"; \ 442 std__cout << " - Message: " << e.what() << std::endl; \ 446 catch (std::exception& e) \ 448 TEST::this_test = false; \ 449 TEST::test = false; \ 450 TEST::all_tests = false; \ 452 TEST::initialNewline(); \ 453 std__cout << "Error: Caught unexpected std::exception" << std::endl; \ 454 std__cout << " - Message: " << e.what() << std::endl; \ 460 TEST::this_test = false; \ 461 TEST::test = false; \ 462 TEST::all_tests = false; \ 464 TEST::initialNewline(); \ 465 std__cout << "Error: Caught unidentified and unexpected exception - No message." \ 470 if (!TEST::validate(TEST::tmp_file_list)) \ 472 TEST::all_tests = false; \ 475 if (!TEST::all_tests) \ 477 std__cout << "FAILED" << std::endl; \ 478 if (TEST::add_message != "") std__cout << "Message: " \ 479 << TEST::add_message \ 481 std__cout << "Failed lines: "; \ 482 for (OpenMS::Size i = 0; i < TEST::failed_lines_list.size(); ++i) \ 484 std__cout << TEST::failed_lines_list[i] << " "; \ 486 std__cout << std::endl; \ 492 for (OpenMS::Size i = 0; i < TEST::tmp_file_list.size(); ++i) \ 494 if (!OpenMS::File::remove(TEST::tmp_file_list[i])) \ 496 std__cout << "Warning: unable to remove temporary file '" \ 497 << TEST::tmp_file_list[i] \ 502 std__cout << "PASSED"; \ 503 if (TEST::add_message != "") std__cout << " (" << TEST::add_message << ")"; \ 504 std__cout << std::endl; \ 531 #define START_SECTION(name_of_test) \ 533 TEST::newline = false; \ 534 TEST::test_name = # name_of_test; \ 535 TEST::test_count = 0; \ 536 TEST::start_section_line = __LINE__; \ 537 std__cout << "checking " << TEST::test_name << " ... " << std::flush; \ 568 #define END_SECTION \ 572 catch (::OpenMS::Exception::BaseException& e) \ 574 TEST::this_test = false; \ 575 TEST::test = false; \ 576 TEST::all_tests = false; \ 578 TEST::initialNewline(); \ 579 std__cout << "Error: Caught unexpected exception of type '" << e.getName() << "'"; \ 580 if ((e.getLine() > 0) && (std::strcmp(e.getFile(), "") != 0)) \ 582 std__cout << " thrown in line " << e.getLine() << " of file '" << e.getFile() \ 583 << "' in function '" << e.getFunction() << "'"; \ 585 std__cout << " - Message: " << e.what() << std::endl; \ 589 catch (std::exception& e) \ 591 TEST::this_test = false; \ 592 TEST::test = false; \ 593 TEST::all_tests = false; \ 595 TEST::initialNewline(); \ 596 std__cout << "Error: Caught std::exception" << std::endl; \ 597 std__cout << " - Message: " << e.what() << std::endl; \ 603 TEST::this_test = false; \ 604 TEST::test = false; \ 605 TEST::all_tests = false; \ 607 TEST::initialNewline(); \ 608 std__cout << "Error: Caught unidentified and unexpected exception - No message." \ 612 TEST::all_tests = TEST::all_tests && TEST::test; \ 616 std__cout << ": passed" << std::endl; \ 620 std__cout << ": failed" << std::endl; \ 624 if (TEST::test_count == 0) \ 626 bool destructor = false; \ 627 for (OpenMS::Size i = 0; i != TEST::test_name.size(); ++i) \ 629 if (TEST::test_name[i] == '~') \ 635 if (!destructor) std__cout << "Warning: no subtests performed in '" \ 643 std__cout << std::endl; 666 #define TEST_EQUAL(a, b) TEST::testEqual(__FILE__, __LINE__, (a), (# a), (b), (# b)); 679 #define TEST_NOT_EQUAL(a, b) TEST::testNotEqual(__FILE__, __LINE__, (a), (# a), (b), (# b)); 693 #define TEST_STRING_EQUAL(a, b) TEST::testStringEqual(__FILE__, __LINE__, (a), (# a), (b), (# b)); 709 #define TEST_FILE_EQUAL(filename, templatename) \ 711 ++TEST::test_count; \ 712 TEST::equal_files = true; \ 713 TEST::infile.open(filename, std::ios::in); \ 714 TEST::templatefile.open(templatename, std::ios::in); \ 716 if (TEST::infile.good() && TEST::templatefile.good()) \ 718 std::string TEST_FILE__template_line; \ 719 std::string TEST_FILE__line; \ 721 while (TEST::infile.good() && TEST::templatefile.good()) \ 723 TEST::templatefile.getline(TEST::line_buffer, 65535); \ 724 TEST_FILE__template_line = TEST::line_buffer; \ 725 TEST::infile.getline(TEST::line_buffer, 65535); \ 726 TEST_FILE__line = TEST::line_buffer; \ 728 TEST::equal_files &= (TEST_FILE__template_line == TEST_FILE__line); \ 729 if (TEST_FILE__template_line != TEST_FILE__line) \ 732 TEST::initialNewline(); \ 733 std__cout << " TEST_FILE_EQUAL: line mismatch:\n got: '" \ 734 << TEST_FILE__line << "'\n expected: '" \ 735 << TEST_FILE__template_line << "'" << std::endl; \ 742 TEST::equal_files = false; \ 744 TEST::initialNewline(); \ 745 std__cout << " + line " \ 747 << ": TEST_FILE_EQUAL(" \ 751 std__cout << ") : " << " cannot open file: \""; \ 752 if (!TEST::infile.good()) \ 754 std__cout << filename << "\" (input file) "; \ 756 if (!TEST::templatefile.good()) \ 758 std__cout << templatename << "\" (template file) "; \ 760 std__cout << std::endl; \ 764 TEST::infile.close(); \ 765 TEST::templatefile.close(); \ 766 TEST::infile.clear(); \ 767 TEST::templatefile.clear(); \ 769 TEST::this_test = TEST::equal_files; \ 770 TEST::test = TEST::test && TEST::this_test; \ 772 TEST::initialNewline(); \ 773 if (TEST::this_test) \ 775 std__cout << " + line " \ 777 << ": TEST_FILE_EQUAL(" \ 785 std__cout << " - line " \ 787 << ": TEST_FILE_EQUAL(" \ 791 << "): false (different files: " \ 796 TEST::failed_lines_list.push_back(TEST::test_line); \ 816 #define TEST_REAL_SIMILAR(a, b) TEST::testRealSimilar(__FILE__, __LINE__, (a), (# a), TEST::isRealType(a), writtenDigits(a), (b), (# b), TEST::isRealType(b), writtenDigits(b)); 833 #define TEST_STRING_SIMILAR(a, b) TEST::testStringSimilar(__FILE__, __LINE__, (a), (# a), (b), (# b)); 849 #define TEST_FILE_SIMILAR(a, b) \ 851 ++TEST::test_count; \ 852 TEST::test_line = __LINE__; \ 853 TEST::this_test = TEST::isFileSimilar((a), (b)); \ 854 TEST::test = TEST::test && TEST::this_test; \ 856 TEST::initialNewline(); \ 857 if (TEST::this_test) \ 859 std__cout << " + line " << __LINE__ \ 860 << ": TEST_FILE_SIMILAR(" # a "," # b "): absolute: " \ 861 << precisionWrapper(TEST::absdiff) \ 863 << precisionWrapper(TEST::absdiff_max_allowed) \ 865 << precisionWrapper(TEST::ratio) \ 867 << precisionWrapper(TEST::ratio_max_allowed) \ 870 std__cout << "message: \n"; \ 871 std__cout << TEST::fuzzy_message; \ 875 std__cout << " - line " << TEST::test_line << \ 876 ": TEST_FILE_SIMILAR(" # a "," # b ") ... -\n"; \ 877 std__cout << "message: \n"; \ 878 std__cout << TEST::fuzzy_message; \ 879 TEST::failed_lines_list.push_back(TEST::test_line); \ 896 #define TOLERANCE_RELATIVE(a) \ 897 TEST::ratio_max_allowed = (a); \ 899 TEST::initialNewline(); \ 900 std__cout << " + line " << __LINE__ << \ 901 ": TOLERANCE_RELATIVE(" << TEST::ratio_max_allowed << \ 902 ") (\"" # a "\")" << std::endl; \ 916 #define TOLERANCE_ABSOLUTE(a) \ 917 TEST::absdiff_max_allowed = (a); \ 919 TEST::initialNewline(); \ 920 std__cout << " + line " << __LINE__ << \ 921 ": TOLERANCE_ABSOLUTE(" << TEST::absdiff_max_allowed << \ 922 ") (\"" # a "\")" << std::endl; \ 930 #define WHITELIST(a) TEST::setWhitelist(__FILE__, __LINE__, (a)); 944 #define TEST_EXCEPTION(exception_type, command) \ 946 ++TEST::test_count; \ 947 TEST::test_line = __LINE__; \ 948 TEST::exception = 0; \ 953 catch (exception_type) \ 955 TEST::exception = 1; \ 957 catch (::OpenMS::Exception::BaseException e) \ 959 TEST::exception = 2; \ 960 TEST::exception_name = e.getName(); \ 964 TEST::exception = 3; \ 966 TEST::this_test = (TEST::exception == 1); \ 967 TEST::test = TEST::test && TEST::this_test; \ 970 TEST::initialNewline(); \ 971 switch (TEST::exception) \ 974 std__cout << " - line " << TEST::test_line << \ 975 ": TEST_EXCEPTION(" # exception_type "," # command \ 976 "): no exception thrown!" << std::endl; \ 977 TEST::failed_lines_list.push_back(TEST::test_line); \ 980 std__cout << " + line " << TEST::test_line << \ 981 ": TEST_EXCEPTION(" # exception_type "," # command \ 982 "): OK" << std::endl; \ 985 std__cout << " - line " << TEST::test_line << \ 986 ": TEST_EXCEPTION(" # exception_type "," # command \ 987 "): wrong exception thrown! \"" \ 988 << TEST::exception_name << "\"" << std::endl; \ 989 TEST::failed_lines_list.push_back(TEST::test_line); \ 992 std__cout << " - line " << TEST::test_line << \ 993 ": TEST_EXCEPTION(" # exception_type "," # command \ 994 "): wrong exception thrown!" << std::endl; \ 995 TEST::failed_lines_list.push_back(TEST::test_line); \ 1012 #ifdef OPENMS_ASSERTIONS 1013 #define TEST_PRECONDITION_VIOLATED(command) TEST_EXCEPTION(Exception::Precondition, command); 1015 #define TEST_PRECONDITION_VIOLATED(command) STATUS("TEST_PRECONDITION_VIOLATED(" # command ") - skipped"); 1029 #ifdef OPENMS_ASSERTIONS 1030 #define TEST_POSTCONDITION_VIOLATED(command) TEST_EXCEPTION(Exception::Postcondition, command); 1032 #define TEST_POSTCONDITION_VIOLATED(command) STATUS("TEST_POSTCONDITION_VIOLATED(" # command ") - skipped"); 1052 #define TEST_EXCEPTION_WITH_MESSAGE(exception_type, command, message) \ 1054 ++TEST::test_count; \ 1055 TEST::test_line = __LINE__; \ 1056 TEST::exception = 0; \ 1061 catch (exception_type et) \ 1063 if (std::string(et.getMessage()) != std::string(message)) \ 1065 TEST::exception = 4; \ 1066 TEST::exception_message = et.getMessage(); \ 1068 else TEST::exception = 1; \ 1070 catch (::OpenMS::Exception::BaseException e) \ 1072 TEST::exception = 2; \ 1073 TEST::exception_name = e.getName(); \ 1077 TEST::exception = 3; \ 1079 TEST::this_test = (TEST::exception == 1); \ 1080 TEST::test = TEST::test && TEST::this_test; \ 1083 TEST::initialNewline(); \ 1084 switch (TEST::exception) \ 1087 std__cout << " - line " << TEST::test_line << \ 1088 ": TEST_EXCEPTION_WITH_MESSAGE(" # exception_type "," # command ", " # message \ 1089 "): no exception thrown!" << std::endl; \ 1090 TEST::failed_lines_list.push_back(TEST::test_line); \ 1094 std__cout << " + line " << TEST::test_line << \ 1095 ": TEST_EXCEPTION_WITH_MESSAGE(" # exception_type "," # command ", " # message \ 1096 "): OK" << std::endl; \ 1099 std__cout << " - line " << TEST::test_line << \ 1100 ": TEST_EXCEPTION_WITH_MESSAGE(" # exception_type "," # command ", " # message \ 1101 "): wrong exception thrown! \"" << \ 1102 TEST::exception_name << "\"" << std::endl; \ 1103 TEST::failed_lines_list.push_back(TEST::test_line); \ 1106 std__cout << " - line " << TEST::test_line << \ 1107 ": TEST_EXCEPTION_WITH_MESSAGE(" # exception_type "," # command ", " # message \ 1108 "): wrong exception thrown!" << std::endl; \ 1109 TEST::failed_lines_list.push_back(TEST::test_line); \ 1112 std__cout << " - line " << TEST::test_line << \ 1113 ": TEST_EXCEPTION_WITH_MESSAGE(" # exception_type "," # command ", " # message \ 1114 "): exception has wrong message: got '" << \ 1115 TEST::exception_message << \ 1116 "', expected '" << \ 1119 TEST::failed_lines_list.push_back(TEST::test_line); \ 1140 #define NEW_TMP_FILE(filename) \ 1142 filename = TEST::tmpFileName(__FILE__, __LINE__); \ 1143 TEST::tmp_file_list.push_back(filename); \ 1145 TEST::initialNewline(); \ 1146 std__cout << " creating new temporary filename '" \ 1162 #define ABORT_IF(condition) \ 1166 TEST::initialNewline(); \ 1167 std__cout << " - line " << __LINE__ << \ 1168 ": ABORT_IF(" # condition "): TEST ABORTED" << \ 1170 TEST::failed_lines_list.push_back(TEST::test_line); \ 1192 #define STATUS(message) \ 1194 TEST::initialNewline(); \ 1195 std__cout << " line " \ 1211 #define ADD_MESSAGE(message) \ 1212 TEST::add_message = message; 1223 #define NOT_TESTABLE \ 1224 TEST::test_count = 1; 1228 #endif //OPENMS_CONCEPT_CLASSTEST_H double absdiff_max_allowed
Maximum absolute difference of numbers allowed, see TOLERANCE_ABSOLUTE.
int test_count
Counter for the number of elementary tests within the current subsection.
void testStringSimilar(const char *file, int line, const std::string &string_1, const char *string_1_stringified, const std::string &string_2, const char *string_2_stringified)
Compare strings using absdiff_max_allowed and ratio_max_allowed.
std::ifstream templatefile
Template (correct) file used by TEST_FILE_EQUAL.
std::string exception_name
(Used by various macros. Stores the "name" of the exception, if applicable.)
bool newline
(Flags whether a new line is in place, depending on context and verbosity setting. Used by initialNewline() and some macros.)
bool this_test
Status of last elementary test.
std::ifstream infile
Questionable file tested by TEST_FILE_EQUAL.
int start_section_line
Line where current subsection started.
std::vector< std::string > tmp_file_list
List of tmp file names (these will be cleaned up, see NEW_TMP_FILE)
void setWhitelist(const char *const, const int line, const std::string &whitelist)
set the whitelist_
std::string add_message
See ADD_MESSAGE.
double ratio_max
Maximum ratio of numbers observed so far, see TOLERANCE_RELATIVE.
void testEqual(const char *, int line, const T1 &expression_1, const char *expression_1_stringified, const T2 &expression_2, const char *expression_2_stringified)
Definition: ClassTest.h:273
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:47
std::string tmpFileName(const std::string &file, int line)
Creates a temporary file name from the test name and the line.
char line_buffer[65536]
(A buffer for one line from a file. Used by TEST_FILE_EQUAL.)
bool isRealType(float)
This overload returns true; float is a floating point type.
Definition: ClassTest.h:90
Class to hold strings, numeric values, lists of strings and lists of numeric values.
Definition: DataValue.h:57
std::string exception_message
(Used by various macros. Stores the "message" of the exception, if applicable.)
#define std__cout
Provide a point of redirection for testing the test macros, see ClassTest_test.cpp.
Definition: ClassTest.h:66
bool equal_files
(A variable used by TEST_FILE_EQUAL)
void testNotEqual(const char *, int line, const T1 &expression_1, const char *expression_1_stringified, const T2 &expression_2, const char *expression_2_stringified)
Definition: ClassTest.h:304
int exception
(Used by various macros. Indicates a rough category of the exception being caught.)
double ratio
Recent ratio of numbers, see TOLERANCE_RELATIVE.
const char * version_string
Version string supplied with START_TEST.
bool all_tests
Status of the whole test.
int test_line
Line of current elementary test.
void testRealSimilar(const char *file, int line, long double number_1, const char *number_1_stringified, bool number_1_is_realtype, Int number_1_written_digits, long double number_2, const char *number_2_stringified, bool, Int number_2_written_digits)
Compare floating point numbers using absdiff_max_allowed and ratio_max_allowed.
void initialNewline()
make sure we have a newline before results from first subtest
std::string test_name
Name of current subsection.
std::vector< UInt > failed_lines_list
List of all failed lines for summary at the end of the test.
Namespace for class tests.
Definition: ClassTest.h:74
bool isRealSimilar(long double number_1, long double number_2)
used by testRealSimilar()
double absdiff
Recent absolute difference of numbers, see TOLERANCE_ABSOLUTE.
bool isFileSimilar(const std::string &filename_1, const std::string &filename_2)
Compare files using absdiff_max_allowed and ratio_max_allowed.
bool test
Status of the current subsection.
int Int
Signed integer type.
Definition: Types.h:103
double absdiff_max
Maximum difference of numbers observed so far, see TOLERANCE_ABSOLUTE.
bool validate(const std::vector< std::string > &file_names)
Validates the given files against the XML schema (if available)
int verbose
Verbosity level ( "-v" is 1 and "-V" is 2 )
void testStringEqual(const char *file, int line, const std::string &string_1, const char *string_1_stringified, const std::string &string_2, const char *string_2_stringified)
used by TEST_STRING_EQUAL
void printWithPrefix(const std::string &text, const int marked=-1)
print the text, each line gets a prefix, the marked line number gets a special prefix ...
std::string fuzzy_message
Last message from a fuzzy comparison. Written by isRealSimilar(), testStringSimilar(), isFileSimilar(). Read by TEST_REAL_SIMILAR, TEST_STRING_SIMILAR, TEST_FILE_SIMILAR;.
double ratio_max_allowed
Maximum ratio of numbers allowed, see TOLERANCE_RELATIVE.