📄 check_run.c
字号:
#include "config.h"#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdarg.h>#include "check.h"#include "check_error.h"#include "check_list.h"#include "check_impl.h"#include "check_msg.h"#include "check_log.h"enum rinfo { CK_R_SIG, CK_R_PASS, CK_R_EXIT, CK_R_FAIL_TEST, CK_R_FAIL_FIXTURE};enum tf_type { CK_FORK_TEST, CK_NOFORK_TEST, CK_NOFORK_FIXTURE};static void srunner_run_init (SRunner *sr, enum print_output print_mode);static void srunner_run_end (SRunner *sr, enum print_output print_mode);static void srunner_iterate_suites (SRunner *sr, enum print_output print_mode);static void srunner_run_tcase (SRunner *sr, TCase *tc);static int srunner_run_unchecked_setup (SRunner *sr, TCase *tc);static void srunner_run_unchecked_teardown (SRunner *sr, TCase *tc);static TestResult * tcase_run_checked_setup (SRunner *sr, TCase *tc);static void tcase_run_checked_teardown (TCase *tc);static void srunner_iterate_tcase_tfuns (SRunner *sr, TCase *tc);static void srunner_add_failure (SRunner *sr, TestResult *tf);static TestResult *tcase_run_tfun_fork (SRunner *sr, TCase *tc, TF *tf);static TestResult *tcase_run_tfun_nofork (SRunner *sr, TCase *tc, TF *tf);static TestResult *receive_result_info_fork (const char *tcname, const char *tname, int status);static TestResult *receive_result_info_nofork (const char *tcname, const char *tname);static void set_fork_info (TestResult *tr, int status);static void set_nofork_info (TestResult *tr);static char *signal_msg (int sig);static char *pass_msg (void);static char *exit_msg (int exitstatus);static int waserror (int status);#define MSG_LEN 100static void srunner_run_init (SRunner *sr, enum print_output print_mode){ set_fork_status(srunner_fork_status(sr)); setup_messaging(); srunner_init_logging (sr, print_mode); log_srunner_start (sr);}static void srunner_run_end (SRunner *sr, enum print_output print_mode){ log_srunner_end (sr); srunner_end_logging (sr); teardown_messaging(); set_fork_status(CK_FORK); }static void srunner_iterate_suites (SRunner *sr, enum print_output print_mode) { List *slst; List *tcl; TCase *tc; 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_suite_end (sr, s); }}void srunner_run_all (SRunner *sr, enum print_output print_mode){ if (sr == NULL) return; if (print_mode < 0 || print_mode >= CK_LAST) eprintf("Bad print_mode argument to srunner_run_all: %d", __FILE__, __LINE__, print_mode); srunner_run_init (sr, print_mode); srunner_iterate_suites (sr, print_mode); srunner_run_end (sr, print_mode);}static void srunner_add_failure (SRunner *sr, TestResult *tr){ list_add_end (sr->resultlst, tr); /* If the context is either of these, the test has run. */ if ((tr->ctx == CK_CTX_TEST) || (tr->ctx == CK_CTX_TEARDOWN)) sr->stats->n_checked++; if (tr->rtype == CK_FAILURE) sr->stats->n_failed++; else if (tr->rtype == CK_ERROR) sr->stats->n_errors++; }static void srunner_iterate_tcase_tfuns (SRunner *sr, TCase *tc){ List *tfl; TF *tfun; TestResult *tr = NULL; tfl = tc->tflst; for (list_front(tfl); !list_at_end (tfl); list_advance (tfl)) { tfun = list_val (tfl); switch (srunner_fork_status(sr)) { case CK_FORK: tr = tcase_run_tfun_fork (sr, tc, tfun); break; case CK_NOFORK: tr = tcase_run_tfun_nofork (sr, tc, tfun); break; default: eprintf("Bad fork status in SRunner", __FILE__, __LINE__); } srunner_add_failure (sr, tr); log_test_end(sr, tr); }} static int srunner_run_unchecked_setup (SRunner *sr, TCase *tc){ TestResult *tr; List *l; Fixture *f; int rval = 1; set_fork_status(CK_NOFORK); l = tc->unch_sflst; for (list_front(l); !list_at_end(l); list_advance(l)) { send_ctx_info(get_send_key(),CK_CTX_SETUP); f = list_val(l); f->fun(); tr = receive_result_info_nofork (tc->name, "unchecked_setup"); if (tr->rtype != CK_PASS) { srunner_add_failure(sr, tr); rval = 0; break; } free(tr->file); free(tr->msg); free(tr); } set_fork_status(srunner_fork_status(sr)); return rval;}static TestResult * tcase_run_checked_setup (SRunner *sr, TCase *tc){ TestResult *tr = NULL; List *l; Fixture *f; enum fork_status fstat = srunner_fork_status(sr); l = tc->ch_sflst; if (fstat == CK_FORK) { send_ctx_info(get_send_key(),CK_CTX_SETUP); } for (list_front(l); !list_at_end(l); list_advance(l)) { if (fstat == CK_NOFORK) { send_ctx_info(get_send_key(),CK_CTX_SETUP); } f = list_val(l); f->fun(); /* Stop the setup and return the failure if nofork mode. */ if (fstat == CK_NOFORK) { tr = receive_result_info_nofork (tc->name, "checked_setup"); if (tr->rtype != CK_PASS) { break; } free(tr->file); free(tr->msg); free(tr); tr = NULL; } } return tr;}static void tcase_run_checked_teardown (TCase *tc){ List *l; Fixture *f; l = tc->ch_tflst; send_ctx_info(get_send_key(),CK_CTX_TEARDOWN); for (list_front(l); !list_at_end(l); list_advance(l)) { f = list_val(l); f->fun(); }}static void srunner_run_unchecked_teardown (SRunner *sr, TCase *tc){ List *l; Fixture *f; set_fork_status(CK_NOFORK); l = tc->unch_tflst; for (list_front(l); !list_at_end(l); list_advance(l)) { f = list_val(l); send_ctx_info(get_send_key(),CK_CTX_TEARDOWN); f->fun (); } set_fork_status(srunner_fork_status(sr));}static void srunner_run_tcase (SRunner *sr, TCase *tc){ if (srunner_run_unchecked_setup (sr,tc)) { srunner_iterate_tcase_tfuns(sr,tc); srunner_run_unchecked_teardown (sr, tc); }}static TestResult *receive_result_info_fork (const char *tcname, const char *tname, int status){ TestResult *tr; tr = receive_test_result (get_recv_key(), waserror(status)); if (tr == NULL) eprintf("Failed to receive test result", __FILE__, __LINE__); tr->tcname = tcname; tr->tname = tname; set_fork_info(tr, status); return tr;}static TestResult *receive_result_info_nofork (const char *tcname, const char *tname){ TestResult *tr; tr = receive_test_result(get_recv_key(), 0); if (tr == NULL) eprintf("Failed to receive test result", __FILE__, __LINE__); tr->tcname = tcname; tr->tname = tname; set_nofork_info(tr); return tr;}static void set_fork_info (TestResult *tr, int status){ int was_sig = WIFSIGNALED(status); int was_exit = WIFEXITED(status); int exit_status = WEXITSTATUS(status); if (was_sig) { tr->rtype = CK_ERROR; tr->msg = signal_msg(WTERMSIG(status)); } else if (was_exit && exit_status == 0) { tr->rtype = CK_PASS; tr->msg = pass_msg(); } else if (was_exit && exit_status != 0) { if (tr->msg == NULL) { /* early exit */ tr->rtype = CK_ERROR; tr->msg = exit_msg(exit_status); } else { tr->rtype = CK_FAILURE; } }}static void set_nofork_info (TestResult *tr){ if (tr->msg == NULL) { tr->rtype = CK_PASS; tr->msg = pass_msg(); } else { tr->rtype = CK_FAILURE; }}static TestResult *tcase_run_tfun_nofork (SRunner *sr, TCase *tc, TF *tfun){ TestResult *tr; tr = tcase_run_checked_setup(sr, tc); if (tr == NULL) { tfun->fn(); tcase_run_checked_teardown(tc); return receive_result_info_nofork(tc->name, tfun->name); } return tr;} static TestResult *tcase_run_tfun_fork (SRunner *sr, TCase *tc, TF *tfun){ pid_t pid; int status = 0; pid = fork(); if (pid == -1) eprintf ("Unable to fork:",__FILE__,__LINE__); if (pid == 0) { tcase_run_checked_setup (sr, tc); tfun->fn(); tcase_run_checked_teardown (tc); exit(EXIT_SUCCESS); } (void) wait(&status); return receive_result_info_fork (tc->name, tfun->name, status);}static char *signal_msg (int signal){ char *msg = emalloc (MSG_LEN); /* free'd by caller */ snprintf (msg, MSG_LEN, "Received signal %d", signal); return msg;}static char *exit_msg (int exitval){ char *msg = emalloc(MSG_LEN); /* free'd by caller */ snprintf (msg, MSG_LEN, "Early exit with return value %d", exitval); return msg;}static char *pass_msg (void){ char *msg = emalloc(sizeof("Passed")); strcpy (msg, "Passed"); return msg;}enum fork_status srunner_fork_status (SRunner *sr){ if (sr->fstat == CK_FORK_UNSPECIFIED) { char *env = getenv ("CK_FORK"); if (env == NULL) return CK_FORK; if (strcmp (env,"no") == 0) return CK_NOFORK; else return CK_FORK; } else return sr->fstat;}void srunner_set_fork_status (SRunner *sr, enum fork_status fstat){ sr->fstat = fstat;}static int waserror (int status){ int was_sig = WIFSIGNALED (status); int was_exit = WIFEXITED (status); int exit_status = WEXITSTATUS (status); return (was_sig || (was_exit && exit_status != 0));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -