From 70a3c91dc51667fc4fb4eeeffc7e0e95990be604 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Sun, 15 Mar 2015 16:00:21 +0100 Subject: [PATCH] Refactored code to prepare for windows integration --- Makefile.am | 1 + include/criterion/event.h | 3 +- src/event.c | 16 ++++---- src/event.h | 2 +- src/posix-compat.c | 82 +++++++++++++++++++++++++++++++++++++++ src/posix-compat.h | 35 +++++++++++++++++ src/process.c | 49 ++++++++++++----------- src/process.h | 3 +- src/runner.c | 7 ++-- 9 files changed, 162 insertions(+), 36 deletions(-) create mode 100644 src/posix-compat.c create mode 100644 src/posix-compat.h diff --git a/Makefile.am b/Makefile.am index e880bad..482175a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ libcriterion_la_SOURCES = \ src/timer.c \ src/timer.h \ src/ordered-set.c \ + src/posix-compat.c \ src/main.c TARGET = $(PACKAGE)-$(VERSION) diff --git a/include/criterion/event.h b/include/criterion/event.h index 75f4a7c..99c85c8 100644 --- a/include/criterion/event.h +++ b/include/criterion/event.h @@ -25,8 +25,9 @@ # define CRITERION_EVENT_H_ # include +# include -extern int EVENT_PIPE; +extern FILE *g_event_pipe; void send_event(int kind, void *data, size_t size); diff --git a/src/event.c b/src/event.c index 339c477..a6a8b3d 100644 --- a/src/event.c +++ b/src/event.c @@ -22,36 +22,37 @@ * THE SOFTWARE. */ -#include +#include #include #include "criterion/stats.h" +#include "criterion/common.h" #include "criterion/hooks.h" #include "event.h" -int EVENT_PIPE = -1; +FILE *g_event_pipe = NULL; void destroy_event(void *ptr, UNUSED void *meta) { struct event *ev = ptr; free(ev->data); } -struct event *read_event(int fd) { +struct event *read_event(FILE *f) { unsigned kind; - if (read(fd, &kind, sizeof (unsigned)) < (ssize_t) sizeof (unsigned)) + if (fread(&kind, sizeof (unsigned), 1, f) == 0) return NULL; switch (kind) { case ASSERT: { const size_t assert_size = sizeof (struct criterion_assert_stats); unsigned char *buf = malloc(assert_size); - if (read(fd, buf, assert_size) < (ssize_t) assert_size) + if (fread(buf, assert_size, 1, f) == 0) return NULL; return unique_ptr(struct event, { .kind = kind, .data = buf }, destroy_event); } case POST_TEST: { double *elapsed_time = malloc(sizeof (double)); - if (read(fd, elapsed_time, sizeof (double)) < (ssize_t) sizeof (double)) + if (fread(elapsed_time, sizeof (double), 1, f) == 0) return NULL; return unique_ptr(struct event, { .kind = kind, .data = elapsed_time }, destroy_event); @@ -65,5 +66,6 @@ void send_event(int kind, void *data, size_t size) { unsigned char buf[sizeof (int) + size]; memcpy(buf, &kind, sizeof (int)); memcpy(buf + sizeof (int), data, size); - write(EVENT_PIPE, buf, sizeof (int) + size); + if (fwrite(buf, sizeof (int) + size, 1, g_event_pipe) == 0) + abort(); } diff --git a/src/event.h b/src/event.h index 405df73..fc8ce4f 100644 --- a/src/event.h +++ b/src/event.h @@ -31,6 +31,6 @@ struct event { void *data; }; -struct event *read_event(int fd); +struct event *read_event(FILE *f); #endif /* !EVENT_H_ */ diff --git a/src/posix-compat.c b/src/posix-compat.c new file mode 100644 index 0000000..46e26e4 --- /dev/null +++ b/src/posix-compat.c @@ -0,0 +1,82 @@ +#include "posix-compat.h" + +#ifdef _WIN32 +# include +#else +# include +# include +# include +# include +#endif + +#include + +struct proc_handle { +#ifdef _WIN32 + // TODO +#else + pid_t pid; +#endif +}; + +struct pipe_handle { +#ifdef _WIN32 + // TODO +#else + int fds[2]; +#endif +}; + +s_proc_handle *fork_process() { +#ifdef _WIN32 + // TODO +#else + pid_t pid = fork(); + if (pid == -1) + return (void *) -1; + if (pid == 0) + return NULL; + return unique_ptr(s_proc_handle, { pid }); +#endif +} + +void wait_process(s_proc_handle *handle, int *status) { +#ifdef _WIN32 + // TODO +#else + waitpid(handle->pid, status, 0); +#endif +} + +FILE *pipe_in(s_pipe_handle *p) { + close(p->fds[1]); + FILE *in = fdopen(p->fds[0], "r"); + setvbuf(in, NULL, _IONBF, 0); + return in; +} + +FILE *pipe_out(s_pipe_handle *p) { + close(p->fds[0]); + FILE *out = fdopen(p->fds[1], "w"); + setvbuf(out, NULL, _IONBF, 0); + return out; +} + +s_pipe_handle *stdpipe() { +#ifdef _WIN32 + // TODO +#else + int fds[2] = { -1, -1 }; + if (pipe(fds) == -1) + return NULL; + return unique_ptr(s_pipe_handle, {{ fds[0], fds[1] }}); +#endif +} + +s_proc_handle *get_current_process() { + return unique_ptr(s_proc_handle, { getpid() }); +} + +bool is_current_process(s_proc_handle *proc) { + return proc->pid == getpid(); +} diff --git a/src/posix-compat.h b/src/posix-compat.h new file mode 100644 index 0000000..83567f8 --- /dev/null +++ b/src/posix-compat.h @@ -0,0 +1,35 @@ +#ifndef POSIX_COMPAT_H_ +# define POSIX_COMPAT_H_ + +# define _POSIX_SOURCE 1 +# include +# undef _POSIX_SOURCE + +# ifdef _WIN32 +# define WEXITSTATUS(Status) (((Status) & 0xFF00) >> 8) +# define WTERMSIG(Status) ((Status) & 0x7F) +# define WIFEXITED(Status) (WTERMSIG(Status) == 0) +# define WIFSIGNALED(Status) (((signed char) (WTERMSIG(Status) + 1) >> 1) > 0) +# else +# include +# endif + +#include + +struct proc_handle; +typedef struct proc_handle s_proc_handle; + +struct pipe_handle; +typedef struct pipe_handle s_pipe_handle; + +s_pipe_handle *stdpipe(); +FILE *pipe_in(s_pipe_handle *p); +FILE *pipe_out(s_pipe_handle *p); + +s_proc_handle *fork_process(); +void wait_process(s_proc_handle *handle, int *status); + +s_proc_handle *get_current_process(); +bool is_current_process(s_proc_handle *proc); + +#endif /* !POSIX_COMPAT_H_ */ diff --git a/src/process.c b/src/process.c index 0d5689c..c0ebd76 100644 --- a/src/process.c +++ b/src/process.c @@ -22,33 +22,38 @@ * THE SOFTWARE. */ #include -#include -#include -#include +#include #include #include "criterion/types.h" #include "criterion/options.h" #include "process.h" #include "event.h" +#include "posix-compat.h" struct process { - pid_t pid; - int in; + s_proc_handle *proc; + FILE *in; }; -static pid_t g_runner_pid; +static s_proc_handle *g_current_proc; -void set_runner_pid(void) { - g_runner_pid = getpid(); +void set_runner_process(void) { + g_current_proc = get_current_process(); +} + +void unset_runner_process(void) { + sfree(g_current_proc); } bool is_runner(void) { - return g_runner_pid == getpid(); + return is_current_process(g_current_proc); } static void close_process(void *ptr, UNUSED void *meta) { - close(((struct process *) ptr)->in); + struct process *proc = ptr; + fclose(proc->in); + sfree(proc->proc); } struct event *worker_read_event(struct process *proc) { @@ -58,35 +63,33 @@ struct event *worker_read_event(struct process *proc) { struct process *spawn_test_worker(struct criterion_test *test, struct criterion_suite *suite, void (*func)(struct criterion_test *, struct criterion_suite *)) { - int fds[2]; - if (pipe(fds) == -1) + smart s_pipe_handle *pipe = stdpipe(); + if (pipe == NULL) abort(); - pid_t pid = fork(); - if (pid == -1) { + s_proc_handle *proc = fork_process(); + if (proc == (void *) -1) { return NULL; - } else if (!pid) { - close(STDIN_FILENO); - close(fds[0]); - EVENT_PIPE = fds[1]; + } else if (proc == NULL) { + fclose(stdin); + g_event_pipe = pipe_out(pipe); func(test, suite); - close(fds[1]); + fclose(g_event_pipe); fflush(NULL); // flush all opened streams if (criterion_options.no_early_exit) return NULL; else - _exit(0); + _Exit(0); } - close(fds[1]); - return unique_ptr(struct process, { .pid = pid, .in = fds[0] }, close_process); + return unique_ptr(struct process, { .proc = proc, .in = pipe_in(pipe) }, close_process); } struct process_status wait_proc(struct process *proc) { int status; - waitpid(proc->pid, &status, 0); + wait_process(proc->proc, &status); if (WIFEXITED(status)) return (struct process_status) { .kind = EXIT_STATUS, .status = WEXITSTATUS(status) }; diff --git a/src/process.h b/src/process.h index 02f480e..679c17f 100644 --- a/src/process.h +++ b/src/process.h @@ -39,7 +39,8 @@ struct process_status { int status; }; -void set_runner_pid(void); +void set_runner_process(void); +void unset_runner_process(void); bool is_runner(void); struct process_status wait_proc(struct process *proc); struct process *spawn_test_worker(struct criterion_test *test, diff --git a/src/runner.c b/src/runner.c index c4a535e..8f07b22 100644 --- a/src/runner.c +++ b/src/runner.c @@ -23,7 +23,6 @@ */ #include #include -#include #include #include "criterion/criterion.h" #include "criterion/options.h" @@ -203,7 +202,6 @@ static int criterion_run_all_tests_impl(void) { smart struct criterion_test_set *set = criterion_init(); report(PRE_ALL, set); - set_runner_pid(); smart struct criterion_global_stats *stats = stats_init(); map_tests(set, stats, run_test); @@ -216,9 +214,12 @@ static int criterion_run_all_tests_impl(void) { } int criterion_run_all_tests(void) { + set_runner_process(); int res = criterion_run_all_tests_impl(); + unset_runner_process(); + if (res == -1) // if this is the test worker terminating - _exit(0); + _Exit(0); return criterion_options.always_succeed || res; }