00001 #include "testlib_register.h"
00002
00003 #include <vcl_iostream.h>
00004 #include <vcl_string.h>
00005 #include <vcl_vector.h>
00006 #if VCL_HAS_EXCEPTIONS
00007 #include <vcl_exception.h>
00008 #endif
00009
00010 #if defined(VCL_VC) || defined(VCL_BORLAND)
00011 # include <crtdbg.h>
00012 # include <windows.h>
00013 # include <vcl_cstdio.h>
00014
00015 LONG WINAPI vxl_exception_filter( struct _EXCEPTION_POINTERS *ExceptionInfo )
00016 {
00017
00018 PVOID ExceptionAddress = ExceptionInfo->ExceptionRecord->ExceptionAddress;
00019 DWORD ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
00020 DWORD* ExceptionInformation = (DWORD*)ExceptionInfo->ExceptionRecord->ExceptionInformation;
00021
00022 vcl_fprintf(stderr, "\nTOP-LEVEL EXCEPTION HANDLER\n");
00023 switch (ExceptionCode)
00024 {
00025 case EXCEPTION_ACCESS_VIOLATION:
00026 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" failed to %s memory at \"0x%.8x\".\n\n",
00027 ExceptionAddress, ExceptionInformation[0] ? "write to" :"read",
00028 ExceptionInformation[1]);
00029 break;
00030
00031 case EXCEPTION_INT_DIVIDE_BY_ZERO:
00032 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" caused an exception of integer devision by zero.\n\n",
00033 ExceptionAddress);
00034 break;
00035 default:
00036 vcl_fprintf(stderr, "The instruction at \"0x%.8p\" caused an unknown exception (exception code: \"0x%.8x\").\n\n",
00037 ExceptionAddress,
00038 ExceptionCode);
00039 }
00040
00041
00042 vcl_printf("Execution aborted!\n");
00043 return EXCEPTION_EXECUTE_HANDLER;
00044 }
00045 #endif // defined(VCL_WIN32)
00046
00047 #if defined(VCL_BORLAND)
00048 # include <math.h>
00049 # include <float.h>
00050 #endif // defined(VCL_BORLAND)
00051
00052 static vcl_vector<TestMainFunction> testlib_test_func_;
00053 static vcl_vector<vcl_string> testlib_test_name_;
00054
00055 void
00056 list_test_names( vcl_ostream& ostr )
00057 {
00058 ostr << "The registered test names are:\n";
00059 for ( unsigned int i = 0; i < testlib_test_name_.size(); ++i )
00060 ostr << " " << testlib_test_name_[i] << '\n';
00061 ostr << "\nOmitting a test name, or specifying the name \"all\" will run all the tests.\n";
00062 }
00063
00064
00065 void
00066 testlib_enter_stealth_mode()
00067 {
00068
00069 char * env_var1 = getenv("DART_TEST_FROM_DART");
00070 char * env_var2 = getenv("DASHBOARD_TEST_FROM_CTEST");
00071 if ( env_var1 || env_var2 ) {
00072
00073
00074 #if defined(VCL_VC)
00075
00076 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
00077 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
00078
00079
00080 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
00081 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
00082
00083
00084
00085 SetUnhandledExceptionFilter( vxl_exception_filter );
00086 #endif //defined(VCL_VC)
00087
00088
00089 #if defined(VCL_BORLAND)
00090 _control87(MCW_EM, MCW_EM);
00091 #endif // defined(VCL_BORLAND)
00092 }
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 = getenv("DART_TEST_FROM_DART");
00101 char * env_var2 = 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 }