1 #ifndef TEST_UTIL_HPP
2 #define TEST_UTIL_HPP
3
4 #ifdef __cplusplus
5 #include <string>
6 #endif
7 #include "moab/MOABConfig.h"
8 /* Define these here because they are used by many tests
9 * to find the add directory for input files */
10 #define STRINGIFY_(X) #X
11 #define STRINGIFY(X) STRINGIFY_(X)
12
13 #ifdef MESHDIR
14 #ifdef __cplusplus
15 const std::string TestDir( STRINGIFY(MESHDIR) );
16 #else
17 const char* TestDir = STRINGIFY(MESHDIR);
18 #endif
19 #else
20 #error Specify MESHDIR to compile test
21 #endif
22
23 /* How to use this test suite utility:
24 * 1) Write tests that use the CHECK and CHECK_* macros defined below to assert test conditions.
25 * 2) Write a main routine that invokes each test through the RUN_TEST macro
26 * 3) RUN_TEST evaluates to 1 if test failed, zero otherwize. Count failures and print summary.
27 */
28
29 /** Check that A is MB_SUCCESS */
30 #define CHECK_ERR( A ) check_equal( MB_SUCCESS, (A), "MB_SUCCESS", #A, __LINE__, __FILE__ )
31 /** Ensure that A is true */
32 #define CHECK( A ) check_true( (A), #A, __LINE__, __FILE__ )
33 /** Check that two values are equal */
34 #define CHECK_EQUAL( EXP, ACT ) check_equal( (EXP), (ACT), #EXP, #ACT, __LINE__, __FILE__ )
35 /** Check that two real (float or double) values are equal within EPS */
36 #define CHECK_REAL_EQUAL( EXP, ACT, EPS ) check_equal( (EXP), (ACT), (EPS), #EXP, #ACT, __LINE__, __FILE__ )
37 /** Check that two arrays contain the same values in the same order */
38 #define CHECK_ARRAYS_EQUAL( EXP, EXP_LEN, ACT, ACT_LEN ) check_array_equal( (EXP), (EXP_LEN), (ACT), (ACT_LEN), #EXP, #ACT, __LINE__, __FILE__ )
39 /** Check that two CartVect objects contain same values */
40 #define CHECK_VECREAL_EQUAL( EXP, ACT, EPS ) check_equal_cartvect( (EXP), (ACT), (EPS), #EXP, #ACT, __LINE__, __FILE__ )
41 /** Run a test
42 * Argument should be a function with the signature: void func(void)
43 * Evaluates to zero if test is successful, one otherwise.
44 */
45 #define RUN_TEST( FUNC ) run_test( &FUNC, #FUNC )
46
47
48 // Use C++ exceptions to return error state to test runner
49 // Portable, but whole test suite stops if any test segfaults, asserts, etc.
50 #define EXCEPTION_MODE 1
51
52 // Test runner forks separate process for each test.
53 // Difficult to debug tests (with debugger). Not portable to Windows.
54 // Very robust (no test can distrub test running code)
55 #define FORK_MODE 2
56
57 // Use signal handler and long jumps to return error state to test runner.
58 // Might be portable to Windows (not sure). Possibly undefined behavior (e.g. continuing
59 // with next test after catching segfault is technically undefined behavior.)
60 // Also, tests can corrupt heap memory management, interferring with later tests.
61 // Leaks memory on test failure (no stack unwind). This is actually a feature, as
62 // we don't care too much about tests leaking memory and trying to reconver memory
63 // might make things worse, depending on why the test failed.
64 #define LONGJMP_MODE 3
65
66 // If test application hasn't set MODE, set to default
67 #ifndef MODE
68 #if defined(_MSC_VER) || defined(__MINGW32__)
69 # define MODE EXCEPTION_MODE
70 # else
71 # define MODE LONGJMP_MODE
72 # endif
73 #endif
74
75
76
77 /***************************************************************************************
78 * NOTE: The remainder of this file contains the implementation of the above macros.
79 * The above macros constitute the entire intended API.
80 ***************************************************************************************/
81
82 #include <math.h>
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 #ifdef __cplusplus
87 #include <iostream>
88 #include <vector>
89 #include <algorithm>
90 #endif
91
92 /***************************************************************************************
93 * Define What to do when a test fails.
94 ***************************************************************************************/
95
96 // For EXCEPTION_MODE, throw an exception when a test fails.
97 // This will unwind stack, recover memory, etc.
98 #if MODE == EXCEPTION_MODE
99 struct ErrorExcept{};
100 # define FLAG_ERROR throw ErrorExcept()
101 // For FORK_MODE, the test is running in its own processs. Just
102 // terminate the process with a non-zero exit code when the test
103 // fails.
104 #elif MODE == FORK_MODE
105 # include <sys/types.h>
106 # include <sys/wait.h>
107 # include <unistd.h>
108 # include <errno.h>
109 # define FLAG_ERROR exit(1)
110 // For LONGJMP_MODE, we do a long jump to just before the test is
111 // run, with a return value of -1 to indicate failures (positive
112 // return codes are used if the test caused a segfault or other
113 // signal.)
114 #elif MODE == LONGJMP_MODE
115 # include <signal.h>
116 # include <setjmp.h>
117 # define FLAG_ERROR siglongjmp( jmpenv, -1 )
118 #else
119 # error "MODE not set"
120 #endif
121
122 /***************************************************************************************
123 * Setup for LONGJMP_MODE
124 ***************************************************************************************/
125
126 #if MODE == LONGJMP_MODE
127
128 // Variable to hold stack state for longjmp
129 sigjmp_buf jmpenv;
130
131 // Define signal handler used to catch errors such as segfaults.
132 // Signal handler does longjmp with the signal number as the
133 // return value.
134 extern "C" {
sighandler(int sig)135 void sighandler( int sig ) {
136 signal( sig, sighandler );
137 siglongjmp(jmpenv, sig);
138 // should never return from longjmp
139 exit(1);
140 }
141 typedef void (*sigfunc_t)(int);
142 } // extern "C"
143
144 // Helper function to register signal handlers.
sethandler(int sig)145 int sethandler( int sig ) {
146 sigfunc_t h = signal( sig, &sighandler );
147 if (h == SIG_ERR)
148 return 1;
149 // If user-defined signal handler (or signal is ignored),
150 // than unregister our handler.
151 else if (h != SIG_DFL)
152 signal( sig, h );
153 return 0;
154 }
155
156 // Register signal handlers for all defined signals that typicall result
157 // in process termination.
init_signal_handlers()158 int init_signal_handlers()
159 {
160 int result = 0;
161 /* Don't trap these. It is unlikely that a test would ever generate such
162 a signal on its own and trapping them interfers with a user's ability
163 to stop a test. SIGHUP implies that the controlling terminal was closed.
164 If the user does ctrl-C or ctrl-\ (SIGINT and SIGQUIT, respectively) and
165 we trap these then just the current test stops. If we leave the default
166 behavior for them then the whole test suite stops. The latter is likely
167 the desired behavior. SIGTERM is the default signal sent by the 'kill'
168 command.
169 #ifdef SIGHUP
170 result += sethandler( SIGHUP );
171 #endif
172 #ifdef SIGINT
173 result += sethandler( SIGINT );
174 #endif
175 #ifdef SIGQUIT
176 result += sethandler( SIGQUIT );
177 #endif
178 #ifdef SIGTERM
179 result += sethandler( SIGTERM );
180 #endif
181 */
182
183 #ifdef SIGILL
184 result += sethandler( SIGILL );
185 #endif
186 #ifdef SIGTRAP
187 result += sethandler( SIGTRAP );
188 #endif
189 #ifdef SIGABRT
190 result += sethandler( SIGABRT );
191 #endif
192 #ifdef SIGBUS
193 result += sethandler( SIGBUS );
194 #endif
195 #ifdef SIGFPE
196 result += sethandler( SIGFPE );
197 #endif
198 #ifdef SIGSEGV
199 result += sethandler( SIGSEGV );
200 #endif
201
202 /* Catching these causes problems with mpich2 1.3.1p1 and a
203 test should never receive such a signal anyway.
204 #ifdef SIGUSR1
205 result += sethandler( SIGUSR1 );
206 #endif
207 #ifdef SIGUSR2
208 result += sethandler( SIGUSR2 );
209 #endif
210 */
211
212 /* Don't trap SIGCHLD. The only way a test should receive
213 such a signal is if it actually forked a child process.
214 That is unlikely, but if it does happen the test probably
215 wants to handle the signal itself.
216 #ifdef SIGCHLD
217 result += sethandler( SIGCHLD );
218 #endif
219 */
220
221 #ifdef SIGPIPE
222 result += sethandler( SIGPIPE );
223 #endif
224 #ifdef SIGIO
225 result += sethandler( SIGIO );
226 #endif
227 #ifdef SIGSYS
228 result += sethandler( SIGSYS );
229 #endif
230 return result;
231 }
232
233 // Declare a garbage global variable. Use variable initialization to
234 // force call to init_signal_handlers().
235 int junk_init_var = init_signal_handlers();
236
237 #endif // LONGJMP_MODE
238
239
240 /***************************************************************************************
241 * Function to handle failed tests
242 ***************************************************************************************/
243
244 // use a function rather than substituting FLAG_ERROR directly
245 // so we have a convenient place to set a break point
flag_error()246 inline void flag_error()
247 { FLAG_ERROR; }
248
249
250 /***************************************************************************************
251 * The Code to Run Tests
252 ***************************************************************************************/
253
254
255 /* Make sure IS_BUILDING_MB is defined so we can include MBInternals.hpp */
256 #include "moab/Types.hpp"
257 #ifndef IS_BUILDING_MB
258 # define IS_BUILDING_MB
259 # include "Internals.hpp"
260 # undef IS_BUILDING_MB
261 #else
262 # include "Internals.hpp"
263 #endif
264
265 #ifndef TEST_USES_ERR_CODES
266 typedef void (*test_func)(void);
run_test(test_func test,const char * func_name)267 int run_test( test_func test, const char* func_name )
268 #else
269 typedef moab::ErrorCode (*test_func_err)(void);
270 int run_test( test_func_err test, const char* func_name )
271 #endif
272 {
273 printf("Running %s ...\n", func_name );
274
275 #if MODE == EXCEPTION_MODE
276 /* On Windows, run all tests in same process.
277 Flag errors by throwing an exception.
278 */
279 try {
280 (*test)();
281 return 0;
282 }
283 catch (ErrorExcept) {
284 printf( " %s: FAILED\n", func_name );
285 return 1;
286 }
287 catch (...) {
288 printf( " %s: UNCAUGHT EXCEPTION\n", func_name );
289 return 1;
290 }
291
292 #elif MODE == FORK_MODE
293 /* For non-Windows OSs, fork() and run test in child process. */
294 pid_t pid = fork();
295 int status;
296
297 /* Fork failed? */
298 if (pid == -1) {
299 perror( "fork()" );
300 abort(); /* abort all tests (can't fork child processes) */
301 }
302
303 /* If child process*/
304 if (pid == 0) {
305 (*test)(); /* call test function */
306 exit(0); /* if function returned, then it succeeded */
307 }
308
309 /* If here, then parent process */
310
311 /* Wait until child process exits */
312 waitpid( pid, &status, 0 );
313
314 /* Check child exit status */
315 if (WIFSIGNALED(status)) {
316 if (WTERMSIG(status))
317 printf(" %s: TERMINATED (signal %d)\n", func_name, (int)WTERMSIG(status) );
318 if (WCOREDUMP(status))
319 printf(" %s: CORE DUMP\n", func_name);
320 return 1;
321 }
322 else if(WEXITSTATUS(status)) {
323 printf( " %s: FAILED\n", func_name );
324 return 1;
325 }
326 else {
327 return 0;
328 }
329
330 #elif MODE == LONGJMP_MODE
331 // Save stack state at this location.
332 int rval = sigsetjmp( jmpenv, 1 );
333 // If rval is zero, then we haven't run the test yet.
334 // If rval is non-zero then
335 // a) we ran the test
336 // b) the test failed
337 // c) we did a longjmp back to the location where we called setsigjmp.
338
339 // run test
340 if (!rval) {
341 (*test)();
342 return 0;
343 }
344 // some check failed
345 else if (rval == -1) {
346 printf( " %s: FAILED\n", func_name );
347 return 1;
348 }
349 // a signal was raised (e.g. segfault)
350 else {
351 printf( " %s: TERMINATED (signal %d)\n", func_name, rval );
352 return 1;
353 }
354 #else
355 #error "MODE not set"
356 #endif // MODE
357 }
358
359
360
361 /***************************************************************************************
362 * CHECK_EQUAL implementations
363 ***************************************************************************************/
364
365 // Common implementatation for most types
366 #define EQUAL_TEST_IMPL( TEST, TYPE ) if( !(TEST) ) { \
367 printf( "Equality Test Failed: %s == %s\n", sA, sB ); \
368 printf( " at line %d of '%s'\n", line, file ); \
369 printf( " Expected value: %" #TYPE "\n", A ); \
370 printf( " Actual value: %" #TYPE "\n", B ); \
371 printf( "\n" ); \
372 flag_error(); \
373 }
374
check_equal(int A,int B,const char * sA,const char * sB,int line,const char * file)375 void check_equal( int A, int B, const char* sA, const char* sB, int line, const char* file )
376 { EQUAL_TEST_IMPL( A == B, d ) }
377
check_equal(unsigned A,unsigned B,const char * sA,const char * sB,int line,const char * file)378 void check_equal( unsigned A, unsigned B, const char* sA, const char* sB, int line, const char* file )
379 { EQUAL_TEST_IMPL( A == B, u ) }
380
check_equal(long A,long B,const char * sA,const char * sB,int line,const char * file)381 void check_equal( long A, long B, const char* sA, const char* sB, int line, const char* file )
382 { EQUAL_TEST_IMPL( A == B, ld ) }
383
check_equal(unsigned long A,unsigned long B,const char * sA,const char * sB,int line,const char * file)384 void check_equal( unsigned long A, unsigned long B, const char* sA, const char* sB, int line, const char* file )
385 { EQUAL_TEST_IMPL( A == B, lu ) }
386
check_equal(unsigned long long A,unsigned long long B,const char * sA,const char * sB,int line,const char * file)387 void check_equal( unsigned long long A, unsigned long long B, const char* sA, const char* sB, int line, const char* file )
388 { EQUAL_TEST_IMPL( A == B, llu ) }
389
check_equal(long long A,long long B,const char * sA,const char * sB,int line,const char * file)390 void check_equal( long long A, long long B, const char* sA, const char* sB, int line, const char* file )
391 { EQUAL_TEST_IMPL( A == B, lld ) }
392
check_equal(void * A,void * B,const char * sA,const char * sB,int line,const char * file)393 void check_equal( void* A, void* B, const char* sA, const char* sB, int line, const char* file )
394 { EQUAL_TEST_IMPL( A == B, p ) }
395
check_equal(const char * A,const char * B,const char * sA,const char * sB,int line,const char * file)396 void check_equal( const char* A, const char* B, const char* sA, const char* sB, int line, const char* file )
397 { EQUAL_TEST_IMPL( !strcmp((A),(B)), s ) }
398
check_equal(const std::string & A,const std::string & B,const char * sA,const char * sB,int line,const char * file)399 void check_equal( const std::string& A, const std::string& B, const char* sA, const char* sB, int line, const char* file )
400 { check_equal( A.c_str(), B.c_str(), sA, sB, line, file); }
401
check_equal(float A,float B,float eps,const char * sA,const char * sB,int line,const char * file)402 void check_equal( float A, float B, float eps, const char* sA, const char* sB, int line, const char* file )
403 { EQUAL_TEST_IMPL( fabsf(A - B) <= eps, f ) }
404
check_equal(double A,double B,double eps,const char * sA,const char * sB,int line,const char * file)405 void check_equal( double A, double B, double eps, const char* sA, const char* sB, int line, const char* file )
406 { EQUAL_TEST_IMPL( fabs(A - B) <= eps, f ) }
407
mb_error_str(moab::ErrorCode err)408 const char* mb_error_str( moab::ErrorCode err )
409 {
410 switch (err) {
411 case moab::MB_SUCCESS : return "Success";
412 case moab::MB_INDEX_OUT_OF_RANGE : return "Index Out of Range";
413 case moab::MB_TYPE_OUT_OF_RANGE : return "Type Out of Range";
414 case moab::MB_MEMORY_ALLOCATION_FAILED: return "Memory Alloc. Failed";
415 case moab::MB_ENTITY_NOT_FOUND : return "Entity Not Found";
416 case moab::MB_MULTIPLE_ENTITIES_FOUND : return "Multiple Entities Found";
417 case moab::MB_TAG_NOT_FOUND : return "Tag Not Found";
418 case moab::MB_FILE_DOES_NOT_EXIST : return "File Not Found";
419 case moab::MB_FILE_WRITE_ERROR : return "File Write Error";
420 case moab::MB_NOT_IMPLEMENTED : return "Not Implemented";
421 case moab::MB_ALREADY_ALLOCATED : return "Already Allocated";
422 case moab::MB_VARIABLE_DATA_LENGTH : return "Variable Data Length";
423 case moab::MB_INVALID_SIZE : return "Invalid Size";
424 case moab::MB_UNSUPPORTED_OPERATION : return "Unsupported Operation";
425 case moab::MB_UNHANDLED_OPTION : return "Unhandled Option";
426 case moab::MB_STRUCTURED_MESH : return "Structured Mesh";
427 case moab::MB_FAILURE : return "Failure";
428 default : return "(unknown)";
429 }
430 }
431
432
433 // Special case for MBErrorCode, use mb_error_str() to print the
434 // string name of the error code.
check_equal(moab::ErrorCode A,moab::ErrorCode B,const char * sA,const char * sB,int line,const char * file)435 void check_equal( moab::ErrorCode A, moab::ErrorCode B, const char* sA, const char* sB, int line, const char* file )
436 {
437 if (A == B)
438 return;
439
440 printf( "ErrorCode Test Failed: %s == %s\n", sA, sB );
441 printf( " at line %d of '%s'\n", line, file );
442 printf( " Expected value: %s (%d)\n", mb_error_str(A), (int)A );
443 printf( " Actual value: %s (%d)\n", mb_error_str(B), (int)B );
444 printf( "\n" );
445 flag_error();
446 }
447
mb_type_str(moab::EntityType type)448 const char* mb_type_str( moab::EntityType type )
449 {
450 switch(type) {
451 case moab::MBVERTEX : return "Vertex";
452 case moab::MBEDGE : return "Edge";
453 case moab::MBTRI : return "Triangle";
454 case moab::MBQUAD : return "Quadrilateral";
455 case moab::MBPOLYGON : return "Polygon";
456 case moab::MBTET : return "Tetrahedron";
457 case moab::MBPYRAMID : return "Pyramid";
458 case moab::MBPRISM : return "Prism (wedge)";
459 case moab::MBKNIFE : return "Knife";
460 case moab::MBHEX : return "Hexahedron";
461 case moab::MBPOLYHEDRON: return "Polyhedron";
462 case moab::MBENTITYSET : return "Entity (Mesh) Set";
463 case moab::MBMAXTYPE : return "(max type)";
464 default : return "(unknown)";
465 }
466 }
467
mb_type_str(moab::EntityHandle a)468 const char* mb_type_str( moab::EntityHandle a )
469 { return mb_type_str( moab::TYPE_FROM_HANDLE(a) ); }
470 /*
471 void check_equal( moab::EntityHandle A, moab::EntityHandle B, const char* sA, const char* sB, int line, const char* file )
472 {
473 if (A == B)
474 return;
475
476 printf( "Entity handles not equal: %s == %s\n", sA, sB );
477 printf( " at line %d of '%s'\n", line, file );
478 if (A)
479 printf( " Expected value: %lx (%s %ld)\n", (unsigned long)A, mb_type_str( A ), (long)ID_FROM_HANDLE(A) );
480 else
481 printf( " Expected value: 0\n" );
482 if (B)
483 printf( " Actual value: %lx (%s %ld)\n", (unsigned long)B, mb_type_str( B ), (long)ID_FROM_HANDLE(B) );
484 else
485 printf( " Actual value: 0\n" );
486 printf( "\n" );
487 flag_error();
488 }
489 */
490
check_true(bool cond,const char * str,int line,const char * file)491 void check_true( bool cond, const char* str, int line, const char* file )
492 {
493 if( !cond ) {
494 printf( "Test Failed: %s\n", str );
495 printf( " at line %d of '%s'\n", line, file );
496 printf( "\n" );
497 flag_error();
498 }
499 }
500
501 #ifdef MB_CART_VECT_HPP
502
check_equal_cartvect(const moab::CartVect & A,const moab::CartVect & B,double eps,const char * sA,const char * sB,int line,const char * file)503 void check_equal_cartvect( const moab::CartVect& A,
504 const moab::CartVect& B, double eps,
505 const char* sA, const char* sB,
506 int line, const char* file )
507 {
508 check_equal( A.length(), B.length(), eps, sA, sB, line, file);
509
510 if( fabs(A[0] - B[0]) <= eps && fabs(A[1] - B[1]) <= eps && fabs(A[2] - B[2]) <= eps )
511 return;
512
513 std::cout << "Equality Test Failed: " << sA << " == " << sB << std::endl;
514 std::cout << " at line " << line << " of '" << file << "'" << std::endl;
515
516 std::cout << " Expected: ";
517 std::cout << A << std::endl;
518
519 std::cout << " Actual: ";
520 std::cout << B << std::endl;
521
522 flag_error();
523 }
524
525 #endif // #ifdef MB_CART_VECT_HPP
526
527 #ifdef __cplusplus
528
529 template <typename T>
check_array_equal(const T * A,size_t A_size,const T * B,size_t B_size,const char * sA,const char * sB,int line,const char * file)530 void check_array_equal( const T* A, size_t A_size,
531 const T* B, size_t B_size,
532 const char* sA, const char* sB,
533 int line, const char* file )
534 {
535 size_t i = 0;
536 for (;;) {
537 if (i == A_size && i == B_size)
538 return; // equal
539 else if (i == A_size || i == B_size)
540 break; // differene lengths
541 else if (A[i] != B[i])
542 break;
543 ++i;
544 }
545
546 std::cout << "Equality Test Failed: " << sA << " == " << sB << std::endl;
547 std::cout << " at line " << line << " of '" << file << "'" << std::endl;
548 std::cout << " Vectors differ at position " << i << std::endl;
549
550 // print at most 10 values, roughly centered on the unequal one
551 size_t count = 10, num_front_values = std::min(count/2,i);
552 size_t max_len = std::max(A_size,B_size);
553 if (i + count - num_front_values > max_len) {
554 if (count > max_len) {
555 num_front_values = i;
556 count = max_len;
557 }
558 else {
559 num_front_values = count - (max_len - i);
560 }
561 }
562
563 std::cout << " Expected: ";
564 if (!A_size) {
565 std::cout << "(empty)" << std::endl;
566 }
567 else {
568 size_t j = i - num_front_values;
569 size_t end = std::min(j + count, A_size);
570 if (j)
571 std::cout << "... ";
572 for (; j < end; ++j) {
573 if (j == i)
574 std::cout << '>' << A[j] << "< ";
575 else
576 std::cout << A[j] << " ";
577 }
578 if (end != A_size)
579 std::cout << "...";
580 std::cout << std::endl;
581 }
582
583 std::cout << " Actual: ";
584 if (!B_size) {
585 std::cout << "(empty)" << std::endl;
586 }
587 else {
588 size_t j = i - num_front_values;
589 size_t end = std::min(j + count, B_size);
590 if (j)
591 std::cout << "... ";
592 for (; j < end; ++j) {
593 if (j == i)
594 std::cout << '>' << B[j] << "< ";
595 else
596 std::cout << B[j] << " ";
597 }
598 if (end != B_size)
599 std::cout << ", ...";
600 std::cout << std::endl;
601 }
602
603 flag_error();
604 }
605
606
607 template <typename T>
check_equal(const std::vector<T> & A,const std::vector<T> & B,const char * sA,const char * sB,int line,const char * file)608 void check_equal( const std::vector<T>& A, const std::vector<T>& B,
609 const char* sA, const char* sB,
610 int line, const char* file )
611 {
612 if(A.empty() || B.empty()) {
613 if(A.size() != B.size()) {
614 std::cout << "Equality Test Failed: " << sA << " == " << sB << std::endl;
615 std::cout << " at line " << line << " of '" << file << "'" << std::endl;
616 std::cout << " Both are not empty " << std::endl;
617 }
618 return;
619 }
620 check_array_equal( &A[0], A.size(), &B[0], B.size(), sA, sB, line, file );
621 }
622
623 #ifdef MOAB_RANGE_HPP
624
check_equal(const moab::Range & A,const moab::Range & B,const char * sA,const char * sB,int line,const char * file)625 void check_equal( const moab::Range& A, const moab::Range& B, const char* sA, const char* sB, int line, const char* file )
626 {
627 if (A == B)
628 return;
629
630 std::cout << "moab::ErrorCode Test Failed: " << sA << " == " << sB << std::endl;
631 std::cout << " at line " << line << " of '" << file << "'" << std::endl;
632 std::cout << " Expected: " << A << std::endl;
633 std::cout << " Actual : " << B << std::endl;
634 std::cout << std::endl;
635 flag_error();
636 }
637
638 #endif // #ifdef MOAB_RANGE_HPP
639
640 #endif /* ifdef __cplusplus */
641
642 #endif
643