MOAB: Mesh Oriented datABase  (version 5.5.0)
TestRunner.hpp File Reference
#include "TestUtil.hpp"
+ Include dependency graph for TestRunner.hpp:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  RunnerTest
 

Macros

#define REGISTER_TEST(TEST_FUNC)   runner_register_test( __FILE__, __LINE__, #TEST_FUNC, ( TEST_FUNC ), NULL )
 
#define REGISTER_DEP_TEST(TEST_FUNC, REQUIRED_FUNC)    runner_register_test( __FILE__, __LINE__, #TEST_FUNC, ( TEST_FUNC ), ( REQUIRED_FUNC ) )
 
#define RUN_TESTS(ARGC, ARGV)   runner_run_tests( ( ARGC ), ( ARGV ) )
 

Enumerations

enum  RunnerStatus { PASSED , FAILED , DESELECTED , SELECTED }
 

Functions

static void runner_register_test (const char *filename, int line_number, const char *name, test_func function, test_func requisite=0)
 
static int runner_run_tests (int argc, char *argv[])
 
static void runner_usage (FILE *str, int argc, char *argv[])
 
static void runner_list_tests (int long_format)
 
static void runner_help (int argc, char *argv[])
 
static size_t runner_find_test_func (test_func f)
 
static size_t runner_find_test_name (const char *name)
 
static size_t runner_add_test (test_func f, const char *name)
 
static void runner_add_requisite (size_t idx, size_t req)
 
static void free_test_list ()
 

Variables

struct RunnerTestRunnerTestList = 0
 
size_t RunnerTestCount = 0
 
const size_t RUNNER_NOT_FOUND = ~(size_t)0
 

Macro Definition Documentation

◆ REGISTER_DEP_TEST

#define REGISTER_DEP_TEST (   TEST_FUNC,
  REQUIRED_FUNC 
)     runner_register_test( __FILE__, __LINE__, #TEST_FUNC, ( TEST_FUNC ), ( REQUIRED_FUNC ) )

Definition at line 22 of file TestRunner.hpp.

◆ REGISTER_TEST

#define REGISTER_TEST (   TEST_FUNC)    runner_register_test( __FILE__, __LINE__, #TEST_FUNC, ( TEST_FUNC ), NULL )

Definition at line 14 of file TestRunner.hpp.

◆ RUN_TESTS

#define RUN_TESTS (   ARGC,
  ARGV 
)    runner_run_tests( ( ARGC ), ( ARGV ) )

Definition at line 31 of file TestRunner.hpp.

Enumeration Type Documentation

◆ RunnerStatus

Enumerator
PASSED 
FAILED 
DESELECTED 
SELECTED 

Definition at line 49 of file TestRunner.hpp.

50 {
51  PASSED,
52  FAILED,
53  DESELECTED,
54  SELECTED
55 };

Function Documentation

◆ free_test_list()

static void free_test_list ( )
static

Definition at line 120 of file TestRunner.hpp.

121 {
122  for( size_t i = 0; i < RunnerTestCount; ++i )
123  {
124  free( RunnerTestList[i].testName );
125  free( RunnerTestList[i].testRequisites );
126  }
127  free( RunnerTestList );
128 }

References RunnerTestCount, RunnerTestList, testName, and RunnerTest::testRequisites.

Referenced by runner_add_test().

◆ runner_add_requisite()

static void runner_add_requisite ( size_t  idx,
size_t  req 
)
static

Definition at line 109 of file TestRunner.hpp.

110 {
111  size_t i;
112  for( i = 0; i < RunnerTestList[idx].numRequisites; ++i )
113  if( RunnerTestList[idx].testRequisites[i] == (int)req ) return;
116  (int*)realloc( RunnerTestList[idx].testRequisites,
117  RunnerTestList[idx].numRequisites * sizeof( *RunnerTestList[idx].testRequisites ) );
119 }

References RunnerTest::numRequisites, RunnerTestList, and RunnerTest::testRequisites.

Referenced by runner_register_test().

◆ runner_add_test()

static size_t runner_add_test ( test_func  f,
const char *  name 
)
static

Definition at line 86 of file TestRunner.hpp.

87 {
88  size_t idx = runner_find_test_func( f );
89  if( idx == RUNNER_NOT_FOUND )
90  {
91  if( !RunnerTestCount ) atexit( &free_test_list );
92  idx = RunnerTestCount++;
93  RunnerTest* new_RunnerTestList = (RunnerTest*)realloc( RunnerTestList, RunnerTestCount * sizeof( RunnerTest ) );
94  if( !new_RunnerTestList )
95  {
96  fprintf( stderr, "TestRunner::runner_add_test(): reallocation of RunnerTestList failed\n" );
97  atexit( &free_test_list );
98  }
99  else
100  RunnerTestList = new_RunnerTestList;
101  RunnerTestList[idx].testFunc = f;
102  RunnerTestList[idx].testName = strdup( name );
105  RunnerTestList[idx].numRequisites = 0;
106  }
107  return idx;
108 }

References free_test_list(), RunnerTest::numRequisites, runner_find_test_func(), RUNNER_NOT_FOUND, RunnerTestCount, RunnerTestList, SELECTED, RunnerTest::testFunc, RunnerTest::testName, RunnerTest::testRequisites, and RunnerTest::testStatus.

Referenced by runner_register_test().

◆ runner_find_test_func()

static size_t runner_find_test_func ( test_func  f)
static

Definition at line 74 of file TestRunner.hpp.

75 {
76  for( size_t i = 0; i < RunnerTestCount; ++i )
77  if( RunnerTestList[i].testFunc == f ) return i;
78  return RUNNER_NOT_FOUND;
79 }

References RUNNER_NOT_FOUND, RunnerTestCount, RunnerTestList, and testFunc.

Referenced by runner_add_test(), and runner_register_test().

◆ runner_find_test_name()

static size_t runner_find_test_name ( const char *  name)
static

Definition at line 80 of file TestRunner.hpp.

81 {
82  for( size_t i = 0; i < RunnerTestCount; ++i )
83  if( !strcmp( RunnerTestList[i].testName, name ) ) return i;
84  return RUNNER_NOT_FOUND;
85 }

References RUNNER_NOT_FOUND, RunnerTestCount, RunnerTestList, and testName.

Referenced by runner_run_tests().

◆ runner_help()

void runner_help ( int  argc,
char *  argv[] 
)
static

Definition at line 155 of file TestRunner.hpp.

156 {
157  runner_usage( stdout, argc, argv );
158  fprintf( stdout, "-l : List test names and exit\n"
159  "-L : List test names and requisites and exit\n"
160  "-h : This help text\n"
161  "-r : Recursively run requisite tests for any specified test\n"
162  "\n" );
163 }

References runner_usage().

Referenced by runner_run_tests().

◆ runner_list_tests()

void runner_list_tests ( int  long_format)
static

Definition at line 165 of file TestRunner.hpp.

166 {
167  size_t i, j;
168  printf( "Test List:\n" );
169  for( i = 0; i < RunnerTestCount; ++i )
170  {
171  if( RunnerTestList[i].testStatus == DESELECTED ) continue;
172  printf( " o %s\n", RunnerTestList[i].testName );
173  if( !long_format || !RunnerTestList[i].numRequisites ) continue;
174  if( RunnerTestList[i].numRequisites == 1 )
175  printf( " Requires : %s\n", RunnerTestList[RunnerTestList[i].testRequisites[0]].testName );
176  else
177  {
178  printf( " Requires : \n" );
179  for( j = 0; j < RunnerTestList[i].numRequisites; ++j )
180  printf( " - %s\n", RunnerTestList[RunnerTestList[i].testRequisites[j]].testName );
181  }
182  }
183 }

References DESELECTED, RunnerTest::numRequisites, RunnerTestCount, RunnerTestList, testName, RunnerTest::testRequisites, and RunnerTest::testStatus.

Referenced by runner_run_tests().

◆ runner_register_test()

void runner_register_test ( const char *  filename,
int  line_number,
const char *  name,
test_func  function,
test_func  requisite = 0 
)
static

Definition at line 130 of file TestRunner.hpp.

131 {
132  size_t i = runner_add_test( test, name );
133  size_t req_idx;
134  if( req )
135  {
136  req_idx = runner_find_test_func( req );
137  if( RUNNER_NOT_FOUND == req_idx )
138  {
139  fprintf( stderr,
140  "Error registering requisite for test: \"%s\"\n"
141  "\tat %s:%d\n"
142  "\tRequisite test function not registered.\n",
143  name, filename, line_number );
144  abort();
145  }
146  runner_add_requisite( i, req_idx );
147  }
148 }

References filename, runner_add_requisite(), runner_add_test(), runner_find_test_func(), RUNNER_NOT_FOUND, and test.

◆ runner_run_tests()

int runner_run_tests ( int  argc,
char *  argv[] 
)
static

Definition at line 185 of file TestRunner.hpp.

186 {
187  /* Counters */
188  int error_count = 0;
189  int fail_count = 0;
190  int num_selected = 0;
191  int num_run = 0;
192 
193  /* Flags from parsed arguments */
194  int run_requisites = 0;
195  int list_tests = 0;
196  int first_selected = 1;
197 
198  /* Misc iterator vars and such */
199  int changed_some, ran_some, can_run, fail;
200  int k;
201  const char* c;
202  size_t i, j;
203 
204  /* Process command line arguments */
205  for( k = 1; k < argc; ++k )
206  {
207  if( argv[k][0] == '-' )
208  {
209  for( c = argv[k] + 1; *c; ++c )
210  {
211  switch( *c )
212  {
213  case 'l':
214  list_tests = 1;
215  break;
216  case 'L':
217  list_tests = 2;
218  break;
219  case 'r':
220  run_requisites = true;
221  break;
222  case 'h':
223  runner_help( argc, argv );
224  return 0;
225  default:
226  runner_usage( stderr, argc, argv );
227  fprintf( stderr, "Unknown flag: '%c'\n", *c );
228  return 1;
229  }
230  }
231  }
232  else
233  {
234  // If user has specified some tests to run, begin
235  // by marking all tests as de-selected.
236  if( first_selected )
237  {
238  for( i = 0; i < RunnerTestCount; ++i )
239  RunnerTestList[i].testStatus = DESELECTED;
240  first_selected = 0;
241  }
242  // Mark specified test as selected.
243  i = runner_find_test_name( argv[k] );
244  if( RUNNER_NOT_FOUND == i )
245  {
246  fprintf( stderr, "Unknown test name: \"%s\"\n", argv[k] );
247  ++error_count;
248  }
249  else
250  {
252  }
253  }
254  }
255 
256  /* If recursively running requisite tests, select those also. */
257  if( run_requisites )
258  {
259  do
260  {
261  changed_some = 0;
262  for( i = 0; i < RunnerTestCount; ++i )
263  {
264  if( RunnerTestList[i].testStatus == DESELECTED ) continue;
265 
266  for( j = 0; j < RunnerTestList[i].numRequisites; ++j )
267  {
268  if( RunnerTestList[RunnerTestList[i].testRequisites[j]].testStatus == DESELECTED )
269  {
271  changed_some = 1;
272  }
273  }
274  }
275  } while( changed_some );
276  }
277 
278  // Count number of selected tests
279  num_selected = 0;
280  for( i = 0; i < RunnerTestCount; ++i )
281  if( RunnerTestList[i].testStatus == SELECTED ) ++num_selected;
282 
283  if( list_tests )
284  {
286  return error_count;
287  }
288 
289  // Now run the tests
290  num_run = 0;
291  do
292  {
293  ran_some = 0;
294  for( i = 0; i < RunnerTestCount; ++i )
295  {
296  if( RunnerTestList[i].testStatus != SELECTED ) continue;
297  can_run = 1;
298  for( j = 0; j < RunnerTestList[i].numRequisites; ++j )
299  {
300  k = RunnerTestList[i].testRequisites[j];
301  if( RunnerTestList[k].testStatus != PASSED && RunnerTestList[k].testStatus != DESELECTED )
302  {
303  can_run = 0;
304  break;
305  }
306  }
307  if( !can_run ) continue;
308 
309  ran_some = 1;
310  ++num_run;
312  if( fail )
313  {
314  error_count++;
315  fail_count++;
317  }
318  else
319  {
321  }
322  }
323  } while( ran_some );
324 
325  // check if we are running parallel MPI tests
326  int rank = 0;
327 #ifdef MOAB_HAVE_MPI
328  int isInit;
329  MPI_Initialized( &isInit );
330  if( isInit )
331  {
332  MPI_Comm_rank( MPI_COMM_WORLD, &rank );
333  }
334 #endif
335 
336  // Print brief summary
337  if( rank == 0 )
338  {
339  if( num_run == (int)RunnerTestCount && !fail_count )
340  {
341  printf( "All %d tests passed.\n", num_run );
342  }
343  else if( num_run == num_selected && !fail_count )
344  {
345  printf( "All %d selected tests passed.\n", num_run );
346  printf( "Skipped %d non-selected tests\n", (int)( RunnerTestCount - num_selected ) );
347  }
348  else
349  {
350  printf( "%2d tests registered\n", (int)RunnerTestCount );
351  if( num_selected == num_run )
352  printf( "%2d tests selected\n", num_selected );
353  else
354  printf( "%2d of %2d tests ran\n", num_run, num_selected );
355  if( num_run < (int)RunnerTestCount )
356  printf( "%2d of %2d tests skipped\n", (int)RunnerTestCount - num_run, (int)RunnerTestCount );
357  printf( "%2d of %2d tests passed\n", num_run - fail_count, num_run );
358  if( fail_count ) printf( "%2d of %2d tests FAILED\n", fail_count, num_run );
359  }
360  }
361 
362  return error_count;
363 }

References DESELECTED, error_count, fail(), FAILED, list_tests(), MPI_COMM_WORLD, RunnerTest::numRequisites, PASSED, rank, run_test(), runner_find_test_name(), runner_help(), runner_list_tests(), RUNNER_NOT_FOUND, runner_usage(), RunnerTestCount, RunnerTestList, SELECTED, testFunc, testName, RunnerTest::testRequisites, and RunnerTest::testStatus.

◆ runner_usage()

void runner_usage ( FILE *  str,
int  argc,
char *  argv[] 
)
static

Definition at line 150 of file TestRunner.hpp.

151 {
152  fprintf( str, "%s [-l|-L] [-h] [-r] [<test_name> [<test_name> ...]]\n", argv[0] );
153 }

Referenced by runner_help(), and runner_run_tests().

Variable Documentation

◆ RUNNER_NOT_FOUND

const size_t RUNNER_NOT_FOUND = ~(size_t)0

◆ RunnerTestCount

size_t RunnerTestCount = 0

◆ RunnerTestList