Logo Search packages:      
Sourcecode: yasm version File versions  Download package

check_run.c

/*
  Check: a unit test framework for C
  Copyright (C) 2001, Arien Malec

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifndef WIFSIGNALED
# define WIFSIGNALED(stat_val)      \
      (((stat_val) & 255) != 255 && \
       ((stat_val) & 255) != 0)
#endif
#ifndef WTERMSIG
# define WTERMSIG(stat_val)   ((stat_val) & 255)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val)  (((stat_val) & 255) == 0)
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val)      ((unsigned)(stat_val) >> 8)
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include <stdio.h>

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stdarg.h>
#endif

#include "error.h"
#include "list.h"
#include "check.h"
#include "check_impl.h"
#include "check_msg.h"
#include "check_log.h"

#ifndef USE_FORKWAITMSG
int nofork_exit_status;
#endif

static void srunner_run_tcase (SRunner *sr, TCase *tc);
static void srunner_add_failure (SRunner *sr, TestResult *tf);
static TestResult *tfun_run (int msqid, const char *tcname, TF *tf);
static TestResult *receive_result_info (int msqid, int status,
                              const char *tcname,
                              const char *tfname);
static void receive_last_loc_info (int msqid, TestResult *tr);
static void receive_failure_info (int msqid, int status, TestResult *tr);
static List *srunner_resultlst (SRunner *sr);


#ifdef USE_FORKWAITMSG
static char *signal_msg (int sig);
#endif
static char *exit_msg (int exitstatus);
static int non_pass (int val);


00085 SRunner *srunner_create (Suite *s)
{
  SRunner *sr = emalloc (sizeof(SRunner)); /* freed in srunner_free */
  sr->slst = list_create();
  list_add_end(sr->slst, s);
  sr->stats = emalloc (sizeof(TestStats)); /* freed in srunner_free */
  sr->stats->n_checked = sr->stats->n_failed = sr->stats->n_errors = 0;
  sr->resultlst = list_create();
  sr->log_fname = NULL;
  sr->loglst = NULL;
  return sr;
}

00098 void srunner_add_suite (SRunner *sr, Suite *s)
{
  list_add_end(sr->slst, s);
}

00103 void srunner_free (SRunner *sr)
{
  List *l;
  TestResult *tr;
  if (sr == NULL)
    return;
  
  free (sr->stats);
  list_free(sr->slst);

  l = sr->resultlst;
  for (list_front(l); !list_at_end(l); list_advance(l)) {
    tr = list_val(l);
    free(tr->file);
    free(tr->msg);
    free(tr);
  }
  list_free (sr->resultlst);

  free (sr);
} 



00127 void srunner_run_all (SRunner *sr, int print_mode)
{
  List *slst;
  List *tcl;
  TCase *tc;
  if (sr == NULL)
    return;
  if (print_mode < 0 || print_mode >= CRLAST)
    eprintf("Bad print_mode argument to srunner_run_all: %d", print_mode);

  srunner_init_logging (sr, print_mode);

  log_srunner_start (sr);

  slst = sr->slst;
  
  for (list_front(slst); !list_at_end(slst); list_advance(slst)) {
    Suite *s = list_val(slst);
    
    log_suite_start (sr, s);

    tcl = s->tclst;
  
    for (list_front(tcl);!list_at_end (tcl); list_advance (tcl)) {
      tc = list_val (tcl);
      srunner_run_tcase (sr, tc);
    }
  }

  log_srunner_end (sr);

  srunner_end_logging (sr);
}

static void srunner_add_failure (SRunner *sr, TestResult *tr)
{
  sr->stats->n_checked++;
  list_add_end (sr->resultlst, tr);
  switch (tr->rtype) {
    
  case CRPASS:
    return;
  case CRFAILURE:
    sr->stats->n_failed++;
    return;
  case CRERROR:
    sr->stats->n_errors++;
    return;
  }
}

  
static void srunner_run_tcase (SRunner *sr, TCase *tc)
{
  List *tfl;
  TF *tfun;
  TestResult *tr;
  int msqid;

  if (tc->setup)
    tc->setup();
  msqid = create_msq();
  tfl = tc->tflst;
  
  for (list_front(tfl); !list_at_end (tfl); list_advance (tfl)) {
    tfun = list_val (tfl);
    tr = tfun_run (msqid, tc->name, tfun);
    srunner_add_failure (sr, tr);
    log_test_end(sr, tr);
  }
  delete_msq(msqid);
  if (tc->teardown)
    tc->teardown();
}

static void receive_last_loc_info (int msqid, TestResult *tr)
{
  LastLocMsg *lmsg;
  lmsg = receive_last_loc_msg (msqid);
  tr->file = last_loc_file (lmsg);
  tr->line = last_loc_line (lmsg);
  free (lmsg);
}  

static void receive_failure_info (int msqid, int status, TestResult *tr)
{
  FailureMsg *fmsg;
#ifdef USE_FORKWAITMSG
  if (WIFSIGNALED(status)) {
    tr->rtype = CRERROR;
    tr->msg = signal_msg (WTERMSIG(status));
    return;
  }
  
  if (WIFEXITED(status)) {
    
    if (WEXITSTATUS(status) == 0) {
      tr->rtype = CRPASS;
      tr->msg = emalloc(strlen("Test passed") + 1);
      strcpy (tr->msg, "Test passed");
    }
    else {
      
      fmsg = receive_failure_msg (msqid);
      if (fmsg == NULL) { /* implies early exit */
      tr->rtype = CRERROR;
      tr->msg =  exit_msg (WEXITSTATUS(status));
      }
      else {
      tr->rtype = CRFAILURE;
      tr->msg = emalloc(strlen(fmsg->msg) + 1);
      strcpy (tr->msg, fmsg->msg);
      free (fmsg);
      }
    }
  } else {
    eprintf ("Bad status from wait() call\n");
  }
#else
  if (status == 0) {
    tr->rtype = CRPASS;
    tr->msg = emalloc(strlen("Test passed") + 1);
    strcpy (tr->msg, "Test passed");
  }
  else {
    fmsg = receive_failure_msg (msqid);
    if (fmsg == NULL) { /* implies early exit */
      tr->rtype = CRERROR;
      tr->msg =  exit_msg (status);
    }
    else {
      tr->rtype = CRFAILURE;
      tr->msg = emalloc(strlen(fmsg->msg) + 1);
      strcpy (tr->msg, fmsg->msg);
      free (fmsg);
    }
  }
#endif
}

static TestResult *receive_result_info (int msqid, int status,
                              const char *tcname, const char *tfname)
{
  TestResult *tr = emalloc (sizeof(TestResult));

  tr->tcname = tcname;
  tr->tfname = tfname;
  receive_last_loc_info (msqid, tr);
  receive_failure_info (msqid, status, tr);
  return tr;
}

static TestResult *tfun_run (int msqid, const char *tcname, TF *tfun)
{
#ifdef USE_FORKWAITMSG
  pid_t pid;
#endif
  int status = 0;

#ifdef USE_FORKWAITMSG
  pid = fork();
  if (pid == -1)
     eprintf ("Unable to fork:");
  if (pid == 0) {
    tfun->fn(msqid);
    _exit(EXIT_SUCCESS);
  }
  (void) wait(&status);
#else
  nofork_exit_status = 0;
  tfun->fn(msqid);
  status = nofork_exit_status;
#endif
  return receive_result_info(msqid, status, tcname, tfun->name);
}




00306 int srunner_ntests_failed (SRunner *sr)
{
  return sr->stats->n_failed + sr->stats->n_errors;
}

00311 int srunner_ntests_run (SRunner *sr)
{
  return sr->stats->n_checked;
}

00316 TestResult **srunner_failures (SRunner *sr)
{
  int i = 0;
  TestResult **trarray;
  List *rlst;
  trarray = malloc (sizeof(trarray[0]) * srunner_ntests_failed (sr));

  rlst = srunner_resultlst (sr);
  for (list_front(rlst); !list_at_end(rlst); list_advance(rlst)) {
    TestResult *tr = list_val(rlst);
    if (non_pass(tr->rtype))
      trarray[i++] = tr;
    
  }
  return trarray;
}

00333 TestResult **srunner_results (SRunner *sr)
{
  int i = 0;
  TestResult **trarray;
  List *rlst;

  trarray = malloc (sizeof(trarray[0]) * srunner_ntests_run (sr));

  rlst = srunner_resultlst (sr);
  for (list_front(rlst); !list_at_end(rlst); list_advance(rlst)) {
    trarray[i++] = list_val(rlst);
  }
  return trarray;
}

static List *srunner_resultlst (SRunner *sr)
{
  return sr->resultlst;
}

00353 char *tr_msg (TestResult *tr)
{
  return tr->msg;
}

00358 int tr_lno (TestResult *tr)
{
  return tr->line;
}

00363 char *tr_lfile (TestResult *tr)
{
  return tr->file;
}

00368 int tr_rtype (TestResult *tr)
{
  return tr->rtype;
}

00373 const char *tr_tcname (TestResult *tr)
{
  return tr->tcname;
}

#ifdef USE_FORKWAITMSG
static char *signal_msg (int signal)
{
  char *msg = emalloc (CMAXMSG); /* free'd by caller */
#ifdef HAVE_SNPRINTF
  snprintf(msg, CMAXMSG, "Received signal %d", signal);
#else
  sprintf(msg, "Received signal %d", signal);
#endif
  return msg;
}
#endif

static char *exit_msg (int exitval)
{
  char *msg = emalloc(CMAXMSG); /* free'd by caller */
#ifdef HAVE_SNPRINTF
  snprintf(msg, CMAXMSG,
         "Early exit with return value %d", exitval);
#else
  sprintf(msg, "Early exit with return value %d", exitval);
#endif
  return msg;
}

static int non_pass (int val)
{
  return val == CRFAILURE || val == CRERROR;
}


Generated by  Doxygen 1.6.0   Back to index