Go to the documentation of this file.00001 #include "testlib_register.h"
00002
00003 #include <vcl_iostream.h>
00004 #include <vcl_string.h>
00005 #include <vcl_vector.h>
00006 #include <vcl_cstdlib.h>
00007 #if VCL_HAS_EXCEPTIONS
00008 #include <vcl_exception.h>
00009 #endif
00010
00011 #if defined(VCL_VC) || defined(VCL_BORLAND)
00012 # include <crtdbg.h>
00013 # include <windows.h>
00014 # include <vcl_cstdio.h>
00015
00016 LONG WINAPI vxl_exception_filter( struct _EXCEPTION_POINTERS *ExceptionInfo )
00017 {
00018
00019 PVOID ExceptionAddress = ExceptionInfo->ExceptionRecord->ExceptionAddress;
00020 DWORD ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
00021 DWORD* ExceptionInformation = (DWORD*)ExceptionInfo->ExceptionRecord->ExceptionInformation;
00022
00023 vcl_fprintf(stderr, "\nTOP-LEVEL EXCEPTION HANDLER\n");
00024 switch (ExceptionCode)
00025 {
00026 case EXCEPTION_ACCESS_VIOLATION:
00027 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" failed to %s memory at \"0x%.8x\".\n\n",
00028 ExceptionAddress, ExceptionInformation[0] ? "write to" :"read",
00029 ExceptionInformation[1]);
00030 break;
00031
00032 case EXCEPTION_INT_DIVIDE_BY_ZERO:
00033 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" caused an exception of integer devision by zero.\n\n",
00034 ExceptionAddress);
00035 break;
00036 default:
00037 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" caused an unknown exception (exception code: \"0x%.8x\").\n\n",
00038 ExceptionAddress,
00039 ExceptionCode);
00040 }
00041
00042
00043 vcl_printf("Execution aborted!\n");
00044 return EXCEPTION_EXECUTE_HANDLER;
00045 }
00046 #endif // defined(VCL_WIN32)
00047
00048 #if defined(VCL_BORLAND)
00049 # include <math.h>
00050 # include <float.h>
00051 #endif // defined(VCL_BORLAND)
00052
00053 static vcl_vector<TestMainFunction> testlib_test_func_;
00054 static vcl_vector<vcl_string> testlib_test_name_;
00055
00056 void
00057 list_test_names( vcl_ostream& ostr )
00058 {
00059 ostr << "The registered test names are:\n";
00060 for ( unsigned int i = 0; i < testlib_test_name_.size(); ++i )
00061 ostr << " " << testlib_test_name_[i] << '\n';
00062 ostr << "\nOmitting a test name, or specifying the name \"all\" will run all the tests.\n";
00063 }
00064
00065
00066 void
00067 testlib_enter_stealth_mode()
00068 {
00069
00070 char * env_var1 = vcl_getenv("DART_TEST_FROM_DART");
00071 char * env_var2 = vcl_getenv("DASHBOARD_TEST_FROM_CTEST");
00072 if ( env_var1 || env_var2 ) {
00073
00074
00075 #if defined(VCL_VC)
00076
00077 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
00078 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
00079
00080
00081 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
00082 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
00083
00084
00085
00086 SetUnhandledExceptionFilter( vxl_exception_filter );
00087 #endif //defined(VCL_VC)
00088
00089
00090 #if defined(VCL_BORLAND)
00091 _control87(MCW_EM, MCW_EM);
00092 #endif // defined(VCL_BORLAND)
00093 }
00094 }
00095
00096
00097 int testlib_run_test_unit(vcl_vector<vcl_string>::size_type i, int argc, char *argv[])
00098 {
00099 #if VCL_HAS_EXCEPTIONS
00100 char * env_var1 = vcl_getenv("DART_TEST_FROM_DART");
00101 char * env_var2 = vcl_getenv("DASHBOARD_TEST_FROM_CTEST");
00102 if ( env_var1 || env_var2 ) {
00103 try {
00104 return testlib_test_func_[i]( argc, argv );
00105 }
00106 catch (const vcl_exception &e)
00107 {
00108 vcl_cerr << "\nTOP-LEVEL EXCEPTION HANDLER **FAILED**\n"
00109 << e.what() << "\n\n";
00110 return 1;
00111 }
00112 }
00113
00114 else
00115 #endif
00116 return testlib_test_func_[i]( argc, argv );
00117 }
00118
00119
00120 int
00121 testlib_main( int argc, char* argv[] )
00122 {
00123
00124
00125
00126 testlib_enter_stealth_mode();
00127
00128
00129
00130 typedef vcl_vector<vcl_string>::size_type vec_size_t;
00131
00132
00133 if ( testlib_test_func_.size() != testlib_test_name_.size() ) {
00134 vcl_cerr << "Error: " << testlib_test_func_.size() << " test functions are registered, but "
00135 << testlib_test_name_.size() << " test names are registered.\n";
00136 return 1;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 bool test_name_given = argc >= 2;
00146
00147 if ( test_name_given && vcl_string("all") == argv[1] )
00148 {
00149 --argc; ++argv; test_name_given = false;
00150 }
00151 if ( test_name_given )
00152 {
00153 for ( vec_size_t i = 0; i < testlib_test_name_.size(); ++i )
00154 if ( testlib_test_name_[i] == argv[1] )
00155 return testlib_run_test_unit(i, argc-1, argv+1);
00156
00157
00158 vcl_cerr << "Test " << argv[1] << " not registered.\n";
00159 list_test_names( vcl_cerr );
00160 }
00161 else
00162 {
00163 vcl_cout << "No test name provided. Attempting to run all tests.\n";
00164 list_test_names( vcl_cout );
00165 vcl_cout << "If you want to run a single test, specify one of the above on the command line.\n\n" << vcl_flush;
00166
00167 bool all_pass = true;
00168 for ( vec_size_t i = 0; i < testlib_test_name_.size(); ++i )
00169 {
00170 vcl_cout << "----------------------------------------\n"
00171 << "Running: " << testlib_test_name_[i] << '\n'
00172 << "----------------------------------------\n" << vcl_flush;
00173
00174 int result = testlib_run_test_unit(i, argc, argv);
00175
00176 vcl_cout << "----------------------------------------\n"
00177 << testlib_test_name_[i] << " returned " << result << ' '
00178 << ( result==0 ? "(PASS)" : "(FAIL)" ) << '\n'
00179 << "----------------------------------------\n" << vcl_flush;
00180 all_pass &= (result == 0);
00181 }
00182
00183 vcl_cout << "\n\nCombined result of " << testlib_test_name_.size() << " tests: "
00184 << ( all_pass ? "PASS" : "FAIL" ) << vcl_endl;
00185 return all_pass ? 0 : 1;
00186 }
00187
00188 return 1;
00189 }
00190
00191 void testlib_register_test(const vcl_string & name, TestMainFunction func)
00192 {
00193 testlib_test_func_.push_back(func);
00194 testlib_test_name_.push_back(name);
00195 }
00196
00197
00198 void testlib_cleanup()
00199 {
00200 testlib_test_func_.clear();
00201 testlib_test_func_.clear();
00202 }