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