Lhogho  0.0.028
 All Data Structures Files Functions Variables Typedefs Macros Pages
tester_internal.c File Reference

Go to the source code of this file.

Functions

RESULT parse_line (FILE *input_file, TCHAR **parameter_name, TCHAR **parameter_optipons)
 Parse a comment line in the test case file. More...
 
RESULT extract_args (FILE *input_file, test_case_info *test_info)
 Extracts all argument pairs from test case file. More...
 
static RESULT write_one_line_result (const TCHAR *result, FILE *out_file)
 Writes a line to the expected result file. More...
 
RESULT extract_expected_results (FILE *input_file, const char *file_name)
 Extract value for expected results from test case file. More...
 
RESULT execute_test (const char *file_name, test_case_info test_info)
 Execute a test case. More...
 
RESULT compile_test (const char *file_name, test_case_info test_info)
 Compile test case file to executable. More...
 
static RESULT get_file_size (const char *file_name, UINT64 *size_ptr)
 Calculate file size. More...
 
RESULT check_results (const char *file_name, test_case_info test_info, UINT32 exec_result)
 Check results from test case execution. More...
 
RESULT import_results (const char *file_name, test_case_info test_info)
 Import results from test execution into test case file. More...
 
void clean_up (const char *file_name)
 Clean up any temporary data from test execution. More...
 
void print_file (const char *file_name, FILE *output_file)
 prints a file to the end of another one More...
 
static RESULT compare_strings_output (const TCHAR *test_line, const TCHAR *expected_line)
 Compare result strings. More...
 
RESULT file_compare (const char *test_file_name, test_case_info test_info)
 Compare result file with one expected. More...
 
RESULT exec_shell (const char *file_name)
 Execute a shell script with name same as test file name. More...
 

Variables

int g_first
 

Function Documentation

RESULT parse_line ( FILE *  input_file,
TCHAR **  parameter_name,
TCHAR **  parameter_optipons 
)
Parameters
input_filefile to read from
parameter_namename of the parameter readed
parameter_optiponspointer to data assigned to the parameter
Returns
RESULT value. See error.h for details

Read a comment line from test case file. If line describes valid parameter-value pair assignes name of parameter to parameter_name and option value to parameter_optipons Allocates memory for them. If line is empty return SUCCESS_EMPTY value If other error occurs return some error value.

Definition at line 51 of file tester_internal.c.

52 {
53  TCHAR buffer[MAX_LINE_LENGTH];
54  TCHAR * str, *start, *end;
55  size_t read_size;
56 
57  m_fgets(input_file, buffer, MAX_LINE_LENGTH, &read_size);
58  if (!read_size)
59  {
60  return SUCCESS_EMPTY;
61  }
62  str = buffer;
63  while (*str && m_isspace(*str))
64  {
65  ++str;
66  }
67  if (!*str)
68  {
69  return SUCCESS_EMPTY;
70  }
71 
72  // Skiping shell comments
73  if (str[0] == '#' && str[1] == '!' && g_first)
74  {
75  g_first = 0;
76  return parse_line(input_file, parameter_name, parameter_optipons);
77  }
78 
79  if (*str != COMMENT_SYMBOL)
80  {
81  LOG_ERROR("parse_line - no comment line");
82  return ERR_GENERIC;
83  }
84 
85  while (*str == COMMENT_SYMBOL || m_isspace(*str))
86  {
87  ++str;
88  }
89 
90  start = str;
91  while (*str && *str != PARAM_SET_SYMBOL)
92  {
93  ++str;
94  }
95  if (*str)
96  {
97  end = str;
98  --str;
99  while(str > start && m_isspace(*str))
100  --str;
101  if (str == start)
102  {
103  LOG_ERROR("parse_line - no param name");
104  return ERR_GENERIC;
105  }
106  if (*str != PARAM_SET_SYMBOL)
107  ++str;
108 
109  *parameter_name = (TCHAR*)malloc((str - start + 1) * sizeof(TCHAR));
110  str[0] = 0;
111  m_strcpy(*parameter_name, start);
112  }
113  else
114  {
115  LOG_ERROR("parse_line - no value specified");
116  return SUCCESS_EMPTY;
117  }
118 
119  str = end+1;
120  while (*str && m_isspace(*str))
121  {
122  ++str;
123  }
124  m_strdup(parameter_optipons, str);
125  return SUCCESS_FULL;
126 }
RESULT extract_args ( FILE *  input_file,
test_case_info test_info 
)
Parameters
input_filefile to read from
test_infostruct in which data from parameters will be writen
Returns
RESULT value. See error.h for details

Reads comment lines from the source file until empty is found For each extracts data and call all registered parsers. Each of them is responsible to process parameter or return ERR_INVALID_ARG if doesn't recognise the param name

Definition at line 142 of file tester_internal.c.

143 {
144  TCHAR * test_name = NULL;
145  TCHAR * test_options = NULL;
146  RESULT res;
147  int i;
148 
149  g_first = 1;
150 
151  while ((res = parse_line(input_file, &test_name, &test_options)) != SUCCESS_EMPTY)
152  {
153  if (IS_ERROR(res))
154  {
155  LOG_ERROR("Couldn't read parameter from input file");
156  break;
157  }
158  for (i = 0; i < PARSERS_COUNT; ++i)
159  {
160  if (g_parsers[i])
161  {
162  res = g_parsers[i](test_name, test_options, test_info);
163  if (IS_ERROR(res) && res != ERR_INVALID_ARG)
164  {
165  break;
166  }
167  }
168  }
169  free (test_name);
170  free (test_options);
171 
172  res = SUCCESS_FULL;
173  }
174 
175  return IS_ERROR(res) ? res : SUCCESS_FULL;
176 }
RESULT write_one_line_result ( const TCHAR result,
FILE *  out_file 
)
static
Parameters
resultline to be written
out_filefile to write in
Returns
RESULT value. See error.h for details

Write a line extracted from test case file to the file containing expected results. Perform some processing on it such as skiping comment symbol.

Definition at line 191 of file tester_internal.c.

192 {
193  if (!result || !out_file)
194  {
195  return ERR_INVALID_ARG;
196  }
197  if (*result != COMMENT_SYMBOL)
198  {
199  return SUCCESS_EMPTY;
200  }
201 
202  ++result; /* skip COMMENT_SYMBOL */
203 
204  if (result)
205  {
206  fwrite(result, m_strlen(result) * sizeof(TCHAR), 1, out_file);
207  }
208  return SUCCESS_FULL;
209 }
RESULT extract_expected_results ( FILE *  input_file,
const char *  file_name 
)
Parameters
input_fileTest case file
file_namename of the file
Returns
RESULT value. See error.h for details

Read lines with expected results from test case file until empty found. Write them after corresponding processment to the file with name similar to file_name but with specified suffix.

Definition at line 223 of file tester_internal.c.

224 {
225  TCHAR buffer [MAX_LINE_LENGTH];
226  TCHAR * str;
227  size_t real_read_size;
228  RESULT res = SUCCESS_FULL;
229  char new_file_name [MAX_LINE_LENGTH];
230  FILE * test_file = NULL;
231 
232  strcpy(new_file_name, file_name);
233  strcat(new_file_name, "."EXPECTED_RESULTS_EXT);
234 
235  if (!(test_file = fopen(new_file_name, "wb")))
236  {
237  return ERR_FILE;
238  }
239 
240  do
241  {
242  str = m_fgets(input_file, buffer, MAX_LINE_LENGTH, &real_read_size);
243 
244  while (str && *str && m_isspace(*str))
245  {
246  ++str;
247  }
248  res = write_one_line_result(str, test_file);
249  }while (res == SUCCESS_FULL);
250 
251  fclose(test_file);
252  return IS_ERROR(res) ? res : SUCCESS_FULL;
253 }
RESULT execute_test ( const char *  file_name,
test_case_info  test_info 
)
Parameters
file_nameTest case file name
test_infoOptions for execution
Returns
execution code as RESULT value

Prepare shell comand line calling tested application and execute it. Depending on testing mode could perform different actions. Collect stdout output and return execution success code as SUCCESS result

Definition at line 267 of file tester_internal.c.

268 {
269  char cmd_buffer[MAX_LINE_LENGTH] = "";
270  int ret;
271 
272 #if defined(__WIN32__) && defined (__GNUC__)
273  // If executed in Cygwin there is problem with system primitive
274  // 'cause system is calling 'cmd' , not 'bash'
275  strcpy(cmd_buffer, "bash -c \"");
276 #endif
277 
280  {
281  /* will compile a source */
283  {
284  strcat(cmd_buffer, g_parameters.compiler_name);
285  }
286  else
287  {
288  strcat(cmd_buffer, LOGO_NAME);
289  }
290  strcat(cmd_buffer, " ");
291  }
292  else
293  {
294  /* will execute precompiled program */
295  char * end = (char *)strrchr(file_name, '.');
296  if (end) *end = '\0';
297  strcpy(cmd_buffer, file_name);
298  if (end) *end = '.';
299  }
300 
301 
303  {
304  strcat(cmd_buffer, MEMORY_CHECK_OPTION);
305  strcat(cmd_buffer, " ");
306  }
307 
309  {
310  strcat(cmd_buffer, g_parameters.global_params);
311  strcat(cmd_buffer, " ");
312  }
313 
314  if (test_info.command_line_param)
315  {
316  strcat(cmd_buffer, test_info.command_line_param);
317  strcat(cmd_buffer, " ");
318  }
319 
322  {
323  strcat(cmd_buffer, file_name);
324  }
325 
326  strcat(cmd_buffer, " 1> ");
327  strcat(cmd_buffer, file_name);
328  strcat(cmd_buffer, "."REAL_RESULTS_EXT);
329  strcat(cmd_buffer, " 2> ");
330  strcat(cmd_buffer, file_name);
331  strcat(cmd_buffer, "."ERROR_RESULTS_EXT);
332 
333 #if defined(__WIN32__) && defined (__GNUC__)
334  strcat(cmd_buffer, "\"");
335 #endif
336 
337  ret = system(cmd_buffer);
338  if (ret == -1)
339  {
340  LOG_ERROR("execution failed");
341  return ERR_GENERIC;
342  }
343  return MAKE_SUCCESS(ret);
344 }
RESULT compile_test ( const char *  file_name,
test_case_info  test_info 
)
Parameters
file_nameTest case file name
test_infoOptions for execution
Returns
RESULT value. See error.h for details

Calls external compiler to compile test file.

Definition at line 356 of file tester_internal.c.

357 {
358  char cmd_buffer[MAX_LINE_LENGTH];
359  int ret;
360 
362  {
363  strcpy(cmd_buffer, g_parameters.compiler_name);
364  }
365  else
366  {
367  strcpy(cmd_buffer, LOGO_NAME);
368  }
369  strcat(cmd_buffer, " -x ");
370 
372  {
373  strcat(cmd_buffer, g_parameters.global_params);
374  strcat(cmd_buffer, " ");
375  }
376 
377  if (test_info.command_line_param)
378  {
379  strcat(cmd_buffer, test_info.command_line_param);
380  strcat(cmd_buffer, " ");
381  }
382 
383  strcat(cmd_buffer, file_name);
384 
385  if ((ret = system(cmd_buffer)) == -1)
386  {
387  LOG_ERROR("execution failed");
388  return ERR_GENERIC;
389  }
390  return MAKE_SUCCESS(ret);
391 }
RESULT get_file_size ( const char *  file_name,
UINT64 size_ptr 
)
static
Parameters
file_namename of input file
size_ptrpointer to the file size.
Returns
RESULT value. See error.h for details

Determine size of file given by file name.

Definition at line 404 of file tester_internal.c.

405 {
406  struct stat info;
407  if (stat(file_name, &info))
408  {
409  return ERR_FILE;
410  }
411  *size_ptr = info.st_size;
412  return SUCCESS_FULL;
413 }
RESULT check_results ( const char *  file_name,
test_case_info  test_info,
UINT32  exec_result 
)
Parameters
file_namename of tested file
test_infooptions for execution
exec_resultreturn value from execution
Returns
RESULT value. See error.h for details

Checks results from test execution and compare them with expected.

Definition at line 426 of file tester_internal.c.

427 {
428  BOOL is_success = TRUE;
429  UINT64 size;
430  RESULT res;
431  char par_name[MAX_NAME_LEN];
432  size_t file_name_len;
433 
434  file_name_len = m_strlen(file_name);
435  strcpy(par_name, file_name);
436 
437  if (0 && exec_result) // No exit code tests now!
438  {
440  {
441  fprintf(g_parameters.output_file, "Error executing test :");
442  m_fputs(g_parameters.output_file, test_info.test_name ? test_info.test_name : file_name);
443  fprintf(g_parameters.output_file, "Exit code : %u\n", exec_result);
444  }
445  return MAKE_SUCCESS(exec_result);
446  }
447 
448  strcpy(par_name + file_name_len, "."ERROR_RESULTS_EXT);
449  res = get_file_size(par_name, &size);
450  if (IS_ERROR(res))
451  {
452  LOG_ERROR("get_file_size failed");
453  return res;
454  }
455  if (size)
456  {
458  {
459  fprintf(g_parameters.output_file, "Executing test ");
460  m_fputs(g_parameters.output_file, test_info.test_name ? test_info.test_name : file_name);
461  fprintf(g_parameters.output_file, " caused output to stderr\n");
463  }
464  return MAKE_SUCCESS((UINT32)size);
465  }
466 
467  if (res = file_compare(file_name, test_info))
468  {
469  return res;
470  }
471 
473  {
474  fprintf(g_parameters.output_file, "Executing test ");
475  m_fputs(g_parameters.output_file, test_info.test_name ? test_info.test_name : file_name);
476  fprintf(g_parameters.output_file, " success!\n");
477  }
478 
480  {
481  fprintf(g_parameters.output_file, " %d (",g_parameters.num_passed );
482  const char* c = test_info.test_name ? test_info.test_name : file_name;
483  c = strrchr (c, '/')+1;
485  fprintf(g_parameters.output_file, ") \r");
486  }
487 
488  return SUCCESS_FULL;
489 }
RESULT import_results ( const char *  file_name,
test_case_info  test_info 
)
Parameters
file_namename of tested file
test_infooptions for execution
Returns
RESULT value. See error.h for details

Import results from test execution into test case file.

Definition at line 501 of file tester_internal.c.

502 {
503  TCHAR line[MAX_LINE_LENGTH];
504  size_t real_size;
505 
506  char exp_name[MAX_NAME_LEN];
507  char temp_name[MAX_NAME_LEN];
508 
509  FILE * expected_file;
510  FILE * source_file;
511  FILE * temp_file;
512 
513 
514  strcpy(exp_name, file_name);
515  strcat(exp_name, "."REAL_RESULTS_EXT);
516  expected_file = fopen(exp_name, "rb");
517  if (!expected_file)
518  {
519  LOG_ERROR("Can't open expected file");
520  return ERR_FILE;
521  }
522 
523  strcpy(temp_name, file_name);
524  strcat(temp_name, "."LTEMP_EXT);
525  temp_file = fopen(temp_name, "wb");
526  if (!temp_file)
527  {
528  LOG_ERROR("Can't open temp file");
529  return ERR_FILE;
530  }
531 
532  source_file = fopen(file_name, "rb");
533  if (!source_file)
534  {
535  LOG_ERROR("Can't open source file");
536  return ERR_FILE;
537  }
538 
539  fprintf(temp_file, "\n");
540 
541  while (m_fgets(expected_file, line, MAX_LINE_LENGTH, &real_size))
542  {
543  if (real_size && real_size < MAX_LINE_LENGTH)
544  {
545  m_fputc(temp_file, COMMENT_SYMBOL);
546  }
547  m_fputs(temp_file, line);
548  }
549 
550  fprintf(temp_file, "\n");
551  fclose(expected_file);
552  unlink(exp_name);
553 
554  while (m_fgets(source_file, line, MAX_LINE_LENGTH, &real_size))
555  {
556  m_fputs(temp_file, line);
557  }
558  fclose(temp_file);
559  fclose(source_file);
560  unlink(file_name);
561  return rename(temp_name, file_name) == 0 ? SUCCESS_FULL : ERR_FILE;
562 }
void clean_up ( const char *  file_name)
Parameters
file_namename of tested file

Remove any temporary files produced from test execution process

Definition at line 572 of file tester_internal.c.

573 {
574  char name[MAX_NAME_LEN];
575  size_t file_name_len;
576 
577  file_name_len = m_strlen(file_name);
578  strcpy(name, file_name);
579 
580  strcpy(name + file_name_len, "."EXPECTED_RESULTS_EXT);
581  unlink(name);
582 
583  strcpy(name + file_name_len, "."REAL_RESULTS_EXT);
584  unlink(name);
585 
586  strcpy(name + file_name_len, "."ERROR_RESULTS_EXT);
587  unlink(name);
588 }
void print_file ( const char *  file_name,
FILE *  output_file 
)
Parameters
file_namename of file to be printed
output_filefile where data will be appended

Appends contet of input file into end of destination file

Definition at line 599 of file tester_internal.c.

600 {
601  TCHAR buffer[MAX_LINE_LENGTH];
602  size_t size;
603 
604  FILE * f = fopen(file_name, "rb");
605  if (!f)
606  {
607  LOG_ERROR("Open file to print failed");
608  return;
609  }
610  while(m_fgets(f, buffer, MAX_LINE_LENGTH, &size))
611  {
612  m_fputs(output_file, buffer);
613  }
614  fclose(f);
615 }
RESULT compare_strings_output ( const TCHAR test_line,
const TCHAR expected_line 
)
static
Parameters
test_lineline produced from test case
expected_lineline expected to be produced

Compare produced from tester data with one expected to be produced. Additional processing on data and sensitiwity of comparisson may be added. Returns success value if lines are "equual" and error if tey are not

Definition at line 629 of file tester_internal.c.

630 {
632  {
633  TCHAR * test_end, ch_test;
634  TCHAR * expect_end, ch_exp;
635  int compare_res;
636 
637  while (m_isspace(*expected_line))
638  ++expected_line;
639 
640  while (m_isspace(*test_line))
641  ++test_line;
642 
643  test_end = (TCHAR*)test_line + m_strlen(test_line) - 1;
644  while (test_end > test_line && m_isspace(*test_end))
645  --test_end;
646  ch_test = test_end[1];
647  test_end[1] = 0;
648 
649 
650  expect_end = (TCHAR*)expected_line + m_strlen(expected_line) - 1;
651 
652  while (expect_end > expected_line && m_isspace(*expect_end))
653  --expect_end;
654 
655  ch_exp = expect_end[1];
656  expect_end[1] = 0;
657 
658  compare_res = m_strcmp(test_line, expected_line);
659  test_end[1] = ch_test;
660  expect_end[1] = ch_exp;
661 
662  return compare_res ? ERR_GENERIC : SUCCESS_FULL;
663  }
664  else
665  {
666  return (m_strcmp(test_line, expected_line)==0 ? SUCCESS_FULL : ERR_GENERIC);
667  }
668 }
RESULT file_compare ( const char *  test_file_name,
test_case_info  test_info 
)
Parameters
test_file_namename of tested file
test_infoparameters for test execution
Returns
RESULT value. See error.h for details

Compare file containing produced from tester data with file containing expected data Returns success value if lines are "equual" and error if tey are not

Definition at line 682 of file tester_internal.c.

683 {
684  TCHAR expected[MAX_LINE_LENGTH];
685  TCHAR expected_mem[] = EXPECTED_MEMORY;
686  TCHAR real[MAX_LINE_LENGTH];
687  size_t real_size, exp_size;
688  char name[MAX_NAME_LEN];
689  RESULT res = SUCCESS_FULL;
690  int mem_checked = 0;
691 
692  FILE * expected_file;
693  FILE * real_file;
694 
695  strcpy(name, test_file_name);
696  strcat(name, "."EXPECTED_RESULTS_EXT);
697  expected_file = fopen(name, "rb");
698  if (!expected_file)
699  {
700  LOG_ERROR("Can't open expected file");
701  return ERR_FILE;
702  }
703 
704  strcpy(name, test_file_name);
705  strcat(name, "."REAL_RESULTS_EXT);
706  real_file = fopen(name, "rb");
707  if (!real_file)
708  {
709  LOG_ERROR("Can't open real file");
710  return ERR_FILE;
711  }
712 
713  while (m_fgets(real_file, real, MAX_LINE_LENGTH, &real_size))
714  {
715  if (!m_fgets(expected_file, expected, MAX_LINE_LENGTH, &exp_size))
716  {
717  if (!mem_checked)
718  {
719  mem_checked = 1;
720  if (SUCCESS_FULL == compare_strings_output(real, expected_mem))
721  {
722  continue;
723  }
724  }
725 
727  {
728  fprintf(g_parameters.output_file, "Test %s failed. Extra line in output: \n%s\n",
729  test_info.test_name ? test_info.test_name : test_file_name, real);
730  }
731  else
732  {
733  fprintf(g_parameters.output_file, "Test failed\n");
734  }
735  res = ERR_GENERIC;
736  break;
737  }
738  if (IS_ERROR(compare_strings_output(real, expected)))
739  {
741  {
742  fprintf(g_parameters.output_file, "Test %s failed. Unexpected line in output: \n\"%s\"\n"
743  "\tExpected\n\"%s\"\n",
744  test_info.test_name ? test_info.test_name : test_file_name, real, expected);
745  }
746  else
747  {
748  fprintf(g_parameters.output_file, "Test failed\n");
749  }
750  res = ERR_GENERIC;
751  break;
752  }
753  }
754 
755  if (m_fgets(expected_file, expected, MAX_LINE_LENGTH, &exp_size))
756  {
757  int i = 0;
758  if (expected[i])
759  {
761  {
762  fprintf(g_parameters.output_file, "Test %s failed. Extra line in output: \n%s\n",
763  test_info.test_name ? test_info.test_name : test_file_name, real);
764  }
765  else
766  {
767  fprintf(g_parameters.output_file, "Test failed\n");
768  }
769  res = ERR_GENERIC;
770  }
771  }
772 
773  if (!mem_checked)
774  {
776  {
777  fprintf(g_parameters.output_file, "Test %s failed. No memory check performed!\n",
778  test_info.test_name ? test_info.test_name : test_file_name);
779  }
780  else
781  {
782  fprintf(g_parameters.output_file, "Test failed\n");
783  }
784  res = ERR_GENERIC;
785  }
786 
787  fclose(real_file);
788  fclose(expected_file);
789 
790  return res;
791 }
RESULT exec_shell ( const char *  file_name)
Parameters
file_namename of tested file
Returns
RESULT value. Execuion status

Try to execute shell script with name same as input file if any. If no script exist return SUCCESS_FILE else return SUCESS_FULL on successfull execution of ERR_GENERIC on error.

Definition at line 803 of file tester_internal.c.

804 {
805  RESULT res = SUCCESS_FILE;
806  FILE * test_file;
807  char sh_name[512];
808  char command[512] = "bash -c ";
809  size_t len;
810  int ret_code;
811  char * dot_pos = strrchr(file_name, '.');
812 
813  // Prepare shell file name
814  if (dot_pos && dot_pos != file_name)
815  {
816  len = dot_pos - file_name;
817  }
818  else
819  {
820  len = strlen(file_name);
821  }
822 
823  strncpy(sh_name, file_name, len);
824  sh_name[len++] = '.';
825  strcpy(sh_name+len, SHELL_FILE_EXTENSION);
826 
827  // Try to open file
828  test_file = fopen(sh_name, "r");
829  if (!test_file)
830  {
831  return SUCCESS_FILE;
832  }
833  fclose(test_file);
834  ret_code = system(strcat(command, sh_name));
836  {
837  fprintf(stderr, "execution:%s-> %d\n", sh_name, ret_code);
838  }
839  if (g_parameters.intest_flag && ret_code)
840  {
841  fprintf(stderr, "execution:%s-> %d\n", sh_name, ret_code);
842  }
843  if (ret_code == -1) // execution failed!
844  {
845  LOG_ERROR("execution failed");
846  return SUCCESS_FILE;
847  }
848  if (ret_code == 0)
849  {
851  return SUCCESS_FULL;
852  }
853 
855  return ERR_GENERIC;
856 }

Variable Documentation

int g_first

Definition at line 34 of file tester_internal.c.


[ HOME | INDEX | ATOMS | VARS | REFERENCE ]
Lhogho Developer's Documentation
Wed Jul 10 2013