|
Packit |
0b5880 |
/*
|
|
Packit |
0b5880 |
* Check: a unit test framework for C
|
|
Packit |
0b5880 |
* Copyright (C) 2001, 2002 Arien Malec
|
|
Packit |
0b5880 |
*
|
|
Packit |
0b5880 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
0b5880 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
0b5880 |
* License as published by the Free Software Foundation; either
|
|
Packit |
0b5880 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
0b5880 |
*
|
|
Packit |
0b5880 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
0b5880 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0b5880 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0b5880 |
* Lesser General Public License for more details.
|
|
Packit |
0b5880 |
*
|
|
Packit |
0b5880 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
0b5880 |
* License along with this library; if not, write to the
|
|
Packit |
0b5880 |
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
Packit |
0b5880 |
* MA 02110-1301, USA.
|
|
Packit |
0b5880 |
*/
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#include "../lib/libcompat.h"
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#include <sys/types.h>
|
|
Packit |
0b5880 |
#include <time.h>
|
|
Packit |
0b5880 |
#include <stdlib.h>
|
|
Packit |
0b5880 |
#include <stdio.h>
|
|
Packit |
0b5880 |
#include <string.h>
|
|
Packit |
0b5880 |
#include <stdarg.h>
|
|
Packit |
0b5880 |
#include <signal.h>
|
|
Packit |
0b5880 |
#include <setjmp.h>
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#include "check.h"
|
|
Packit |
0b5880 |
#include "check_error.h"
|
|
Packit |
0b5880 |
#include "check_list.h"
|
|
Packit |
0b5880 |
#include "check_impl.h"
|
|
Packit |
0b5880 |
#include "check_msg.h"
|
|
Packit |
0b5880 |
#include "check_log.h"
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
enum rinfo
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
CK_R_SIG,
|
|
Packit |
0b5880 |
CK_R_PASS,
|
|
Packit |
0b5880 |
CK_R_EXIT,
|
|
Packit |
0b5880 |
CK_R_FAIL_TEST,
|
|
Packit |
0b5880 |
CK_R_FAIL_FIXTURE
|
|
Packit |
0b5880 |
};
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
enum tf_type
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
CK_FORK_TEST,
|
|
Packit |
0b5880 |
CK_NOFORK_TEST,
|
|
Packit |
0b5880 |
CK_NOFORK_FIXTURE
|
|
Packit |
0b5880 |
};
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* all functions are defined in the same order they are declared.
|
|
Packit |
0b5880 |
functions that depend on forking are gathered all together.
|
|
Packit |
0b5880 |
non-static functions are at the end of the file. */
|
|
Packit |
0b5880 |
static void srunner_run_init(SRunner * sr, enum print_output print_mode);
|
|
Packit |
0b5880 |
static void srunner_run_end(SRunner * sr, enum print_output print_mode);
|
|
Packit |
0b5880 |
static void srunner_iterate_suites(SRunner * sr,
|
|
Packit |
0b5880 |
const char *sname, const char *tcname,
|
|
Packit |
0b5880 |
const char *include_tags,
|
|
Packit |
0b5880 |
const char *exclude_tags,
|
|
Packit |
0b5880 |
enum print_output print_mode);
|
|
Packit |
0b5880 |
static void srunner_iterate_tcase_tfuns(SRunner * sr, TCase * tc);
|
|
Packit |
0b5880 |
static void srunner_add_failure(SRunner * sr, TestResult * tf);
|
|
Packit |
0b5880 |
static TestResult * srunner_run_setup(List * func_list,
|
|
Packit |
0b5880 |
enum fork_status fork_usage, const char * test_name,
|
|
Packit |
0b5880 |
const char * setup_name);
|
|
Packit |
0b5880 |
static int srunner_run_unchecked_setup(SRunner * sr, TCase * tc);
|
|
Packit |
0b5880 |
static TestResult *tcase_run_checked_setup(SRunner * sr, TCase * tc);
|
|
Packit |
0b5880 |
static void srunner_run_teardown(List * fixture_list, enum fork_status fork_usage);
|
|
Packit |
0b5880 |
static void srunner_run_unchecked_teardown(SRunner * sr, TCase * tc);
|
|
Packit |
0b5880 |
static void tcase_run_checked_teardown(TCase * tc);
|
|
Packit |
0b5880 |
static void srunner_run_tcase(SRunner * sr, TCase * tc);
|
|
Packit |
0b5880 |
static TestResult *tcase_run_tfun_nofork(SRunner * sr, TCase * tc, TF * tf,
|
|
Packit |
0b5880 |
int i);
|
|
Packit |
0b5880 |
static TestResult *receive_result_info_nofork(const char *tcname,
|
|
Packit |
0b5880 |
const char *tname, int iter,
|
|
Packit |
0b5880 |
int duration);
|
|
Packit |
0b5880 |
static void set_nofork_info(TestResult * tr);
|
|
Packit |
0b5880 |
static char *pass_msg(void);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
static TestResult *tcase_run_tfun_fork(SRunner * sr, TCase * tc, TF * tf,
|
|
Packit |
0b5880 |
int i);
|
|
Packit |
0b5880 |
static TestResult *receive_result_info_fork(const char *tcname,
|
|
Packit |
0b5880 |
const char *tname, int iter,
|
|
Packit |
0b5880 |
int status, int expected_signal,
|
|
Packit |
0b5880 |
signed char allowed_exit_value);
|
|
Packit |
0b5880 |
static void set_fork_info(TestResult * tr, int status, int expected_signal,
|
|
Packit |
0b5880 |
signed char allowed_exit_value);
|
|
Packit |
0b5880 |
static char *signal_msg(int sig);
|
|
Packit |
0b5880 |
static char *signal_error_msg(int signal_received, int signal_expected);
|
|
Packit |
0b5880 |
static char *exit_msg(int exitstatus);
|
|
Packit |
0b5880 |
static int waserror(int status, int expected_signal);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static int alarm_received;
|
|
Packit |
0b5880 |
static pid_t group_pid;
|
|
Packit |
0b5880 |
static struct sigaction sigint_old_action;
|
|
Packit |
0b5880 |
static struct sigaction sigterm_old_action;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void CK_ATTRIBUTE_UNUSED sig_handler(int sig_nr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
switch (sig_nr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
case SIGALRM:
|
|
Packit |
0b5880 |
alarm_received = 1;
|
|
Packit |
0b5880 |
killpg(group_pid, SIGKILL);
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
case SIGTERM:
|
|
Packit |
0b5880 |
case SIGINT:
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
pid_t own_group_pid;
|
|
Packit |
0b5880 |
int child_sig = SIGTERM;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if (sig_nr == SIGINT)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
child_sig = SIGKILL;
|
|
Packit |
0b5880 |
sigaction(SIGINT, &sigint_old_action, NULL);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
sigaction(SIGTERM, &sigterm_old_action, NULL);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
killpg(group_pid, child_sig);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* POSIX says that calling killpg(0)
|
|
Packit |
0b5880 |
* does not necessarily mean to call it on the callers
|
|
Packit |
0b5880 |
* group pid! */
|
|
Packit |
0b5880 |
own_group_pid = getpgrp();
|
|
Packit |
0b5880 |
killpg(own_group_pid, sig_nr);
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
default:
|
|
Packit |
0b5880 |
eprintf("Unhandled signal: %d", __FILE__, __LINE__, sig_nr);
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#define MSG_LEN 100
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_run_init(SRunner * sr, enum print_output print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
set_fork_status(srunner_fork_status(sr));
|
|
Packit |
0b5880 |
setup_messaging();
|
|
Packit |
0b5880 |
srunner_init_logging(sr, print_mode);
|
|
Packit |
0b5880 |
log_srunner_start(sr);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_run_end(SRunner * sr,
|
|
Packit |
0b5880 |
enum print_output CK_ATTRIBUTE_UNUSED print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
log_srunner_end(sr);
|
|
Packit |
0b5880 |
srunner_end_logging(sr);
|
|
Packit |
0b5880 |
teardown_messaging();
|
|
Packit |
0b5880 |
set_fork_status(CK_FORK);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_iterate_suites(SRunner * sr,
|
|
Packit |
0b5880 |
const char *sname, const char *tcname,
|
|
Packit |
0b5880 |
const char *include_tags,
|
|
Packit |
0b5880 |
const char *exclude_tags,
|
|
Packit |
0b5880 |
enum print_output CK_ATTRIBUTE_UNUSED
|
|
Packit |
0b5880 |
print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
List *include_tag_lst;
|
|
Packit |
0b5880 |
List *exclude_tag_lst;
|
|
Packit |
0b5880 |
List *slst;
|
|
Packit |
0b5880 |
List *tcl;
|
|
Packit |
0b5880 |
TCase *tc;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
slst = sr->slst;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
include_tag_lst = tag_string_to_list(include_tags);
|
|
Packit |
0b5880 |
exclude_tag_lst = tag_string_to_list(exclude_tags);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(check_list_front(slst); !check_list_at_end(slst);
|
|
Packit |
0b5880 |
check_list_advance(slst))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
Suite *s = (Suite *)check_list_val(slst);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(((sname != NULL) && (strcmp(sname, s->name) != 0))
|
|
Packit |
0b5880 |
|| ((tcname != NULL) && (!suite_tcase(s, tcname))))
|
|
Packit |
0b5880 |
continue;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
log_suite_start(sr, s);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tcl = s->tclst;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(check_list_front(tcl); !check_list_at_end(tcl);
|
|
Packit |
0b5880 |
check_list_advance(tcl))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tc = (TCase *)check_list_val(tcl);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if((tcname != NULL) && (strcmp(tcname, tc->name) != 0))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
continue;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
if (include_tags != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if (!tcase_matching_tag(tc, include_tag_lst))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
continue;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
if (exclude_tags != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if (tcase_matching_tag(tc, exclude_tag_lst))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
continue;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
srunner_run_tcase(sr, tc);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
log_suite_end(sr, s);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
check_list_apply(include_tag_lst, free);
|
|
Packit |
0b5880 |
check_list_apply(exclude_tag_lst, free);
|
|
Packit |
0b5880 |
check_list_free(include_tag_lst);
|
|
Packit |
0b5880 |
check_list_free(exclude_tag_lst);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_iterate_tcase_tfuns(SRunner * sr, TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
List *tfl;
|
|
Packit |
0b5880 |
TF *tfun;
|
|
Packit |
0b5880 |
TestResult *tr = NULL;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tfl = tc->tflst;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(check_list_front(tfl); !check_list_at_end(tfl);
|
|
Packit |
0b5880 |
check_list_advance(tfl))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
int i;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tfun = (TF *)check_list_val(tfl);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(i = tfun->loop_start; i < tfun->loop_end; i++)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
log_test_start(sr, tc, tfun);
|
|
Packit |
0b5880 |
switch (srunner_fork_status(sr))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
case CK_FORK:
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
tr = tcase_run_tfun_fork(sr, tc, tfun, i);
|
|
Packit |
0b5880 |
#else /* HAVE_FORK */
|
|
Packit |
0b5880 |
eprintf("This version does not support fork", __FILE__,
|
|
Packit |
0b5880 |
__LINE__);
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
case CK_NOFORK:
|
|
Packit |
0b5880 |
tr = tcase_run_tfun_nofork(sr, tc, tfun, i);
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
case CK_FORK_GETENV:
|
|
Packit |
0b5880 |
default:
|
|
Packit |
0b5880 |
eprintf("Bad fork status in SRunner", __FILE__, __LINE__);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(NULL != tr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_add_failure(sr, tr);
|
|
Packit |
0b5880 |
log_test_end(sr, tr);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_add_failure(SRunner * sr, TestResult * tr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
check_list_add_end(sr->resultlst, tr);
|
|
Packit |
0b5880 |
sr->stats->n_checked++; /* count checks during setup, test, and teardown */
|
|
Packit |
0b5880 |
if(tr->rtype == CK_FAILURE)
|
|
Packit |
0b5880 |
sr->stats->n_failed++;
|
|
Packit |
0b5880 |
else if(tr->rtype == CK_ERROR)
|
|
Packit |
0b5880 |
sr->stats->n_errors++;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static TestResult * srunner_run_setup(List * fixture_list, enum fork_status fork_usage,
|
|
Packit |
0b5880 |
const char * test_name, const char * setup_name)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr = NULL;
|
|
Packit |
0b5880 |
Fixture *setup_fixture;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(fork_usage == CK_FORK)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
send_ctx_info(CK_CTX_SETUP);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(check_list_front(fixture_list); !check_list_at_end(fixture_list);
|
|
Packit |
0b5880 |
check_list_advance(fixture_list))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
setup_fixture = (Fixture *)check_list_val(fixture_list);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(fork_usage == CK_NOFORK)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
send_ctx_info(CK_CTX_SETUP);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(0 == setjmp(error_jmp_buffer))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
setup_fixture->fun();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* Stop the setup and return the failure in nofork mode. */
|
|
Packit |
0b5880 |
tr = receive_result_info_nofork(test_name, setup_name, 0, -1);
|
|
Packit |
0b5880 |
if(tr->rtype != CK_PASS)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
free(tr->file);
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
free(tr);
|
|
Packit |
0b5880 |
tr = NULL;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
setup_fixture->fun();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return tr;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static int srunner_run_unchecked_setup(SRunner * sr, TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr = NULL;
|
|
Packit |
0b5880 |
int rval = 1;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
set_fork_status(CK_NOFORK);
|
|
Packit |
0b5880 |
tr = srunner_run_setup(tc->unch_sflst, CK_NOFORK, tc->name, "unchecked_setup");
|
|
Packit |
0b5880 |
set_fork_status(srunner_fork_status(sr));
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(tr != NULL && tr->rtype != CK_PASS)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_add_failure(sr, tr);
|
|
Packit |
0b5880 |
rval = 0;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return rval;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static TestResult *tcase_run_checked_setup(SRunner * sr, TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr = srunner_run_setup(tc->ch_sflst, srunner_fork_status(sr),
|
|
Packit |
0b5880 |
tc->name, "checked_setup");
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return tr;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_run_teardown(List * fixture_list, enum fork_status fork_usage)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
Fixture * fixture;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
for(check_list_front(fixture_list); !check_list_at_end(fixture_list);
|
|
Packit |
0b5880 |
check_list_advance(fixture_list))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
fixture = (Fixture *)check_list_val(fixture_list);
|
|
Packit |
0b5880 |
send_ctx_info(CK_CTX_TEARDOWN);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(fork_usage == CK_NOFORK)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(0 == setjmp(error_jmp_buffer))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
fixture->fun();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* Abort the remaining teardowns */
|
|
Packit |
0b5880 |
break;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
fixture->fun();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_run_unchecked_teardown(SRunner * sr, TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_run_teardown(tc->unch_tflst, srunner_fork_status(sr));
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void tcase_run_checked_teardown(TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_run_teardown(tc->ch_tflst, CK_NOFORK);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void srunner_run_tcase(SRunner * sr, TCase * tc)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(srunner_run_unchecked_setup(sr, tc))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_iterate_tcase_tfuns(sr, tc);
|
|
Packit |
0b5880 |
srunner_run_unchecked_teardown(sr, tc);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static TestResult *tcase_run_tfun_nofork(SRunner * sr, TCase * tc, TF * tfun,
|
|
Packit |
0b5880 |
int i)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr;
|
|
Packit |
0b5880 |
struct timespec ts_start = {0, 0}, ts_end = {0, 0};
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tr = tcase_run_checked_setup(sr, tc);
|
|
Packit |
0b5880 |
if(tr == NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
clock_gettime(check_get_clockid(), &ts_start);
|
|
Packit |
0b5880 |
if(0 == setjmp(error_jmp_buffer))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tfun->fn(i);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
clock_gettime(check_get_clockid(), &ts_end);
|
|
Packit |
0b5880 |
tcase_run_checked_teardown(tc);
|
|
Packit |
0b5880 |
return receive_result_info_nofork(tc->name, tfun->name, i,
|
|
Packit |
0b5880 |
DIFF_IN_USEC(ts_start, ts_end));
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return tr;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static TestResult *receive_result_info_nofork(const char *tcname,
|
|
Packit |
0b5880 |
const char *tname,
|
|
Packit |
0b5880 |
int iter, int duration)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tr = receive_test_result(0);
|
|
Packit |
0b5880 |
if(tr == NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
eprintf("Failed to receive test result", __FILE__, __LINE__);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->tcname = tcname;
|
|
Packit |
0b5880 |
tr->tname = tname;
|
|
Packit |
0b5880 |
tr->iter = iter;
|
|
Packit |
0b5880 |
tr->duration = duration;
|
|
Packit |
0b5880 |
set_nofork_info(tr);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return tr;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void set_nofork_info(TestResult * tr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(tr->msg == NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_PASS;
|
|
Packit |
0b5880 |
tr->msg = pass_msg();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_FAILURE;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static char *pass_msg(void)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
return strdup("Passed");
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
static TestResult *tcase_run_tfun_fork(SRunner * sr, TCase * tc, TF * tfun,
|
|
Packit |
0b5880 |
int i)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
pid_t pid_w;
|
|
Packit |
0b5880 |
pid_t pid;
|
|
Packit |
0b5880 |
int status = 0;
|
|
Packit |
0b5880 |
struct timespec ts_start = { 0, 0 }, ts_end ={ 0, 0 };
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
timer_t timerid;
|
|
Packit |
0b5880 |
struct itimerspec timer_spec;
|
|
Packit |
0b5880 |
TestResult *tr;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
pid = fork();
|
|
Packit |
0b5880 |
if(pid == -1)
|
|
Packit |
0b5880 |
eprintf("Error in call to fork:", __FILE__, __LINE__ - 2);
|
|
Packit |
0b5880 |
if(pid == 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
setpgid(0, 0);
|
|
Packit |
0b5880 |
group_pid = getpgrp();
|
|
Packit |
0b5880 |
tr = tcase_run_checked_setup(sr, tc);
|
|
Packit |
0b5880 |
free(tr);
|
|
Packit |
0b5880 |
clock_gettime(check_get_clockid(), &ts_start);
|
|
Packit |
0b5880 |
tfun->fn(i);
|
|
Packit |
0b5880 |
clock_gettime(check_get_clockid(), &ts_end);
|
|
Packit |
0b5880 |
tcase_run_checked_teardown(tc);
|
|
Packit |
0b5880 |
send_duration_info(DIFF_IN_USEC(ts_start, ts_end));
|
|
Packit |
0b5880 |
exit(EXIT_SUCCESS);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
group_pid = pid;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
alarm_received = 0;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(timer_create(check_get_clockid(),
|
|
Packit |
0b5880 |
NULL /* fire SIGALRM if timer expires */,
|
|
Packit |
0b5880 |
&timerid) == 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* Set the timer to fire once */
|
|
Packit |
0b5880 |
timer_spec.it_value = tc->timeout;
|
|
Packit |
0b5880 |
timer_spec.it_interval.tv_sec = 0;
|
|
Packit |
0b5880 |
timer_spec.it_interval.tv_nsec = 0;
|
|
Packit |
0b5880 |
if(timer_settime(timerid, 0, &timer_spec, NULL) == 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
do
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
pid_w = waitpid(pid, &status, 0);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
while(pid_w == -1);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
eprintf("Error in call to timer_settime:", __FILE__, __LINE__);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* If the timer has not fired, disable it */
|
|
Packit |
0b5880 |
timer_delete(timerid);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
eprintf("Error in call to timer_create:", __FILE__, __LINE__);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
killpg(pid, SIGKILL); /* Kill remaining processes. */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return receive_result_info_fork(tc->name, tfun->name, i, status,
|
|
Packit |
0b5880 |
tfun->signal, tfun->allowed_exit_value);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static TestResult *receive_result_info_fork(const char *tcname,
|
|
Packit |
0b5880 |
const char *tname,
|
|
Packit |
0b5880 |
int iter,
|
|
Packit |
0b5880 |
int status, int expected_signal,
|
|
Packit |
0b5880 |
signed char allowed_exit_value)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
TestResult *tr;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
tr = receive_test_result(waserror(status, expected_signal));
|
|
Packit |
0b5880 |
if(tr == NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
eprintf("Failed to receive test result", __FILE__, __LINE__);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->tcname = tcname;
|
|
Packit |
0b5880 |
tr->tname = tname;
|
|
Packit |
0b5880 |
tr->iter = iter;
|
|
Packit |
0b5880 |
set_fork_info(tr, status, expected_signal, allowed_exit_value);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return tr;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static void set_fork_info(TestResult * tr, int status, int signal_expected,
|
|
Packit |
0b5880 |
signed char allowed_exit_value)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
int was_sig = WIFSIGNALED(status);
|
|
Packit |
0b5880 |
int was_exit = WIFEXITED(status);
|
|
Packit |
0b5880 |
signed char exit_status = WEXITSTATUS(status);
|
|
Packit |
0b5880 |
int signal_received = WTERMSIG(status);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(was_sig)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(signal_expected == signal_received)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(alarm_received)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* Got alarm instead of signal */
|
|
Packit |
0b5880 |
tr->rtype = CK_ERROR;
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = signal_error_msg(signal_received, signal_expected);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_PASS;
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = pass_msg();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else if(signal_expected != 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* signal received, but not the expected one */
|
|
Packit |
0b5880 |
tr->rtype = CK_ERROR;
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = signal_error_msg(signal_received, signal_expected);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* signal received and none expected */
|
|
Packit |
0b5880 |
tr->rtype = CK_ERROR;
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = signal_msg(signal_received);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else if(signal_expected == 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(was_exit && exit_status == allowed_exit_value)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_PASS;
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = pass_msg();
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else if(was_exit && exit_status != allowed_exit_value)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(tr->msg == NULL)
|
|
Packit |
0b5880 |
{ /* early exit */
|
|
Packit |
0b5880 |
tr->rtype = CK_ERROR;
|
|
Packit |
0b5880 |
tr->msg = exit_msg(exit_status);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_FAILURE;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{ /* a signal was expected and none raised */
|
|
Packit |
0b5880 |
if(was_exit)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(tr->msg != NULL)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
free(tr->msg);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
tr->msg = exit_msg(exit_status);
|
|
Packit |
0b5880 |
if(exit_status == allowed_exit_value)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_FAILURE; /* normal exit status */
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
tr->rtype = CK_FAILURE; /* early exit */
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static char *signal_msg(int signal)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
char *msg = (char *)emalloc(MSG_LEN); /* free'd by caller */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(alarm_received)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
snprintf(msg, MSG_LEN, "Test timeout expired");
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
snprintf(msg, MSG_LEN, "Received signal %d (%s)",
|
|
Packit |
0b5880 |
signal, strsignal(signal));
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
return msg;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static char *signal_error_msg(int signal_received, int signal_expected)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
char *sig_r_str;
|
|
Packit |
0b5880 |
char *sig_e_str;
|
|
Packit |
0b5880 |
char *msg = (char *)emalloc(MSG_LEN); /* free'd by caller */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
sig_r_str = strdup(strsignal(signal_received));
|
|
Packit |
0b5880 |
sig_e_str = strdup(strsignal(signal_expected));
|
|
Packit |
0b5880 |
if(alarm_received)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
snprintf(msg, MSG_LEN,
|
|
Packit |
0b5880 |
"Test timeout expired, expected signal %d (%s)",
|
|
Packit |
0b5880 |
signal_expected, sig_e_str);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
else
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
snprintf(msg, MSG_LEN, "Received signal %d (%s), expected %d (%s)",
|
|
Packit |
0b5880 |
signal_received, sig_r_str, signal_expected, sig_e_str);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
free(sig_r_str);
|
|
Packit |
0b5880 |
free(sig_e_str);
|
|
Packit |
0b5880 |
return msg;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static char *exit_msg(int exitval)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
char *msg = (char *)emalloc(MSG_LEN); /* free'd by caller */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
snprintf(msg, MSG_LEN, "Early exit with return value %d", exitval);
|
|
Packit |
0b5880 |
return msg;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
static int waserror(int status, int signal_expected)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
int was_sig = WIFSIGNALED(status);
|
|
Packit |
0b5880 |
int was_exit = WIFEXITED(status);
|
|
Packit |
0b5880 |
int exit_status = WEXITSTATUS(status);
|
|
Packit |
0b5880 |
int signal_received = WTERMSIG(status);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
return ((was_sig && (signal_received != signal_expected)) ||
|
|
Packit |
0b5880 |
(was_exit && exit_status != 0));
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
enum fork_status srunner_fork_status(SRunner * sr)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
if(sr->fstat == CK_FORK_GETENV)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
char *env = getenv("CK_FORK");
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(env == NULL)
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
return CK_FORK;
|
|
Packit |
0b5880 |
#else
|
|
Packit |
0b5880 |
return CK_NOFORK;
|
|
Packit |
0b5880 |
#endif
|
|
Packit |
0b5880 |
if(strcmp(env, "no") == 0)
|
|
Packit |
0b5880 |
return CK_NOFORK;
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
return CK_FORK;
|
|
Packit |
0b5880 |
#else /* HAVE_FORK */
|
|
Packit |
0b5880 |
/* Ignoring, as Check is not compiled with fork support. */
|
|
Packit |
0b5880 |
return CK_NOFORK;
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
return sr->fstat;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
void srunner_set_fork_status(SRunner * sr, enum fork_status fstat)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
#if !defined(HAVE_FORK) || HAVE_FORK==0
|
|
Packit |
0b5880 |
/* If fork() is unavailable, do not allow a fork mode to be set */
|
|
Packit |
0b5880 |
if(fstat != CK_NOFORK)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
/* Overriding, as Check is not compiled with fork support. */
|
|
Packit |
0b5880 |
fstat = CK_NOFORK;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
#endif /* ! HAVE_FORK */
|
|
Packit |
0b5880 |
sr->fstat = fstat;
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
void srunner_run_all(SRunner * sr, enum print_output print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_run(sr, NULL, /* All test suites. */
|
|
Packit |
0b5880 |
NULL, /* All test cases. */
|
|
Packit |
0b5880 |
print_mode);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
void srunner_run_tagged(SRunner * sr, const char *sname, const char *tcname,
|
|
Packit |
0b5880 |
const char *include_tags, const char *exclude_tags,
|
|
Packit |
0b5880 |
enum print_output print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
|
Packit |
0b5880 |
static struct sigaction sigalarm_old_action;
|
|
Packit |
0b5880 |
static struct sigaction sigalarm_new_action;
|
|
Packit |
0b5880 |
static struct sigaction sigint_new_action;
|
|
Packit |
0b5880 |
static struct sigaction sigterm_new_action;
|
|
Packit |
0b5880 |
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* Get the selected test suite and test case from the
|
|
Packit |
0b5880 |
environment. */
|
|
Packit |
0b5880 |
if(!tcname)
|
|
Packit |
0b5880 |
tcname = getenv("CK_RUN_CASE");
|
|
Packit |
0b5880 |
if(!sname)
|
|
Packit |
0b5880 |
sname = getenv("CK_RUN_SUITE");
|
|
Packit |
0b5880 |
if(!include_tags)
|
|
Packit |
0b5880 |
include_tags = getenv("CK_INCLUDE_TAGS");
|
|
Packit |
0b5880 |
if(!exclude_tags)
|
|
Packit |
0b5880 |
exclude_tags = getenv("CK_EXCLUDE_TAGS");
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(sr == NULL)
|
|
Packit |
0b5880 |
return;
|
|
Packit |
0b5880 |
if(print_mode >= CK_LAST)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
eprintf("Bad print_mode argument to srunner_run_all: %d",
|
|
Packit |
0b5880 |
__FILE__, __LINE__, print_mode);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
|
Packit |
0b5880 |
memset(&sigalarm_new_action, 0, sizeof(sigalarm_new_action));
|
|
Packit |
0b5880 |
sigalarm_new_action.sa_handler = sig_handler;
|
|
Packit |
0b5880 |
sigaction(SIGALRM, &sigalarm_new_action, &sigalarm_old_action);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
memset(&sigint_new_action, 0, sizeof(sigint_new_action));
|
|
Packit |
0b5880 |
sigint_new_action.sa_handler = sig_handler;
|
|
Packit |
0b5880 |
sigaction(SIGINT, &sigint_new_action, &sigint_old_action);
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
memset(&sigterm_new_action, 0, sizeof(sigterm_new_action));
|
|
Packit |
0b5880 |
sigterm_new_action.sa_handler = sig_handler;
|
|
Packit |
0b5880 |
sigaction(SIGTERM, &sigterm_new_action, &sigterm_old_action);
|
|
Packit |
0b5880 |
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
|
Packit |
0b5880 |
srunner_run_init(sr, print_mode);
|
|
Packit |
0b5880 |
srunner_iterate_suites(sr, sname, tcname, include_tags, exclude_tags,
|
|
Packit |
0b5880 |
print_mode);
|
|
Packit |
0b5880 |
srunner_run_end(sr, print_mode);
|
|
Packit |
0b5880 |
#if defined(HAVE_SIGACTION) && defined(HAVE_FORK)
|
|
Packit |
0b5880 |
sigaction(SIGALRM, &sigalarm_old_action, NULL);
|
|
Packit |
0b5880 |
sigaction(SIGINT, &sigint_old_action, NULL);
|
|
Packit |
0b5880 |
sigaction(SIGTERM, &sigterm_old_action, NULL);
|
|
Packit |
0b5880 |
#endif /* HAVE_SIGACTION && HAVE_FORK */
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
void srunner_run(SRunner * sr, const char *sname, const char *tcname,
|
|
Packit |
0b5880 |
enum print_output print_mode)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
srunner_run_tagged(sr, sname, tcname, NULL, NULL, print_mode);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
pid_t check_fork(void)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
pid_t pid = fork();
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
/* Set the process to a process group to be able to kill it easily. */
|
|
Packit |
0b5880 |
if(pid >= 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
setpgid(pid, group_pid);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
return pid;
|
|
Packit |
0b5880 |
#else /* HAVE_FORK */
|
|
Packit |
0b5880 |
/* Ignoring, as Check is not compiled with fork support. */
|
|
Packit |
0b5880 |
return -1;
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
void check_waitpid_and_exit(pid_t pid CK_ATTRIBUTE_UNUSED)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
#if defined(HAVE_FORK) && HAVE_FORK==1
|
|
Packit |
0b5880 |
pid_t pid_w;
|
|
Packit |
0b5880 |
int status;
|
|
Packit |
0b5880 |
|
|
Packit |
0b5880 |
if(pid > 0)
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
do
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
pid_w = waitpid(pid, &status, 0);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
while(pid_w == -1);
|
|
Packit |
0b5880 |
if(waserror(status, 0))
|
|
Packit |
0b5880 |
{
|
|
Packit |
0b5880 |
exit(EXIT_FAILURE);
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
}
|
|
Packit |
0b5880 |
exit(EXIT_SUCCESS);
|
|
Packit |
0b5880 |
#else /* HAVE_FORK */
|
|
Packit |
0b5880 |
/* Ignoring, as Check is not compiled with fork support. */
|
|
Packit |
0b5880 |
exit(EXIT_FAILURE);
|
|
Packit |
0b5880 |
#endif /* HAVE_FORK */
|
|
Packit |
0b5880 |
}
|