diff --git a/.gitignore b/.gitignore index f95baf79..c4aecd44 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,4 @@ ev/autom4te.cache /Win32/ /x64/ -test/echo-demo -test/test-ping-pong +test/test-runner diff --git a/Makefile b/Makefile index bf6a493c..15fe3ef8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,13 @@ -all: oio.a +all: oio.a test/test-runner + +TESTS=test/echo-server.c \ + test/test-pass-always.c \ + test/test-fail-always.c \ + test/test-ping-pong.c \ + test/test-callback-stack.c + +test/test-runner: test/*.h test/test-runner.c test/test-runner-unix.c $(TESTS) oio.a + $(CC) -ansi -g -lm -o test/test-runner test/test-runner.c test/test-runner-unix.c $(TESTS) oio.a test/echo-demo: test/echo-demo.c test/echo.o oio.a $(CC) -ansi -g -o test/echo-demo test/echo-demo.c test/echo.o oio.a -lm @@ -25,7 +34,7 @@ ev/config.h: .PHONY: clean distclean clean: - $(RM) -f *.o *.a + $(RM) -f *.o *.a test/test-runner $(MAKE) -C ev clean distclean: diff --git a/oio-unix.c b/oio-unix.c index 80ce3a97..2135e194 100644 --- a/oio-unix.c +++ b/oio-unix.c @@ -67,6 +67,11 @@ int oio_run() { } +int oio_tcp_handle_init(oio_handle *handle, oio_close_cb close_cb, void* data) { + return -1; +} + +/* Remove me */ oio_handle* oio_tcp_handle_new(oio_close_cb close_cb, void* data) { oio_handle *handle = calloc(sizeof(oio_handle), 1); if (!handle) { @@ -207,6 +212,12 @@ int oio_listen(oio_handle* handle, int backlog, oio_accept_cb cb) { } +int oio_tcp_handle_accept(oio_handle* server, oio_handle* client, + oio_close_cb close_cb, void* data) { + ; +} + + int oio_close_error(oio_handle* handle, oio_err err) { ev_io_stop(EV_DEFAULT_ &handle->read_watcher); close(handle->fd); diff --git a/test/echo-server.c b/test/echo-server.c index 6ebd4ebd..7f2a438f 100644 --- a/test/echo-server.c +++ b/test/echo-server.c @@ -126,4 +126,4 @@ TEST_IMPL(echo_server) { fprintf(stderr, "Listening!\n"); oio_run(); return 0; -} \ No newline at end of file +} diff --git a/test/test-list.h b/test/test-list.h index 28530a18..a2cb092c 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -13,4 +13,4 @@ TEST_LIST_START TEST_ENTRY (fail_always) TEST_ENTRY (pass_always) -TEST_LIST_END \ No newline at end of file +TEST_LIST_END diff --git a/test/test-runner-unix.c b/test/test-runner-unix.c new file mode 100644 index 00000000..9612f05d --- /dev/null +++ b/test/test-runner-unix.c @@ -0,0 +1,157 @@ +#include "test-runner-unix.h" +#include "test-runner.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PATHMAX 1024 +static char executable_path[PATHMAX] = { '\0' }; + + +/* Linux-only */ +static void get_executable_path() { + if (!executable_path[0]) { + readlink("/proc/self/exe", executable_path, PATHMAX - 1); + } +} + + +/* Invoke "arv[0] test-name". Store process info in *p. */ +/* Make sure that all stdio output of the processes is buffered up. */ +int process_start(char* name, process_info_t* p) { + FILE* stdout_file = tmpfile(); + if (!stdout_file) { + perror("tmpfile"); + return -1; + } + + p->terminated = 0; + + get_executable_path(); + + pid_t pid = vfork(); + + if (pid < 0) { + perror("vfork"); + return -1; + } + + if (pid == 0) { + /* child */ + dup2(fileno(stdout_file), STDOUT_FILENO); + dup2(fileno(stdout_file), STDERR_FILENO); + + char* args[3] = { executable_path, name, NULL }; + execvp(executable_path, args); + perror("execvp()"); + _exit(127); + } + + /* parent */ + p->pid = pid; + p->name = strdup(name); + p->stdout_file = stdout_file; + + return 0; +} + + +/* Wait for all `n` processes in `vec` to terminate. */ +/* Time out after `timeout` msec, or never if timeout == -1 */ +/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */ +int process_wait(process_info_t* vec, int n, int timeout) { + int i; + process_info_t* p; + for (i = 0; i < n; i++) { + p = (process_info_t*)(vec + i * sizeof(process_info_t)); + if (p->terminated) continue; + int status = 0; + int r = waitpid(p->pid, &p->status, 0); + if (r < 0) { + return -1; + } + p->terminated = 1; + } + return 0; +} + + +/* Returns the number of bytes in the stdio output buffer for process `p`. */ +long int process_output_size(process_info_t *p) { + /* Size of the p->stdout_file */ + struct stat buf; + + int r = fstat(fileno(p->stdout_file), &buf); + if (r < 0) { + return -1; + } + + return (long)buf.st_size; +} + + +/* Copy the contents of the stdio output buffer to `fd`. */ +int process_copy_output(process_info_t *p, int fd) { + int r = fseek(p->stdout_file, 0, SEEK_SET); + if (r < 0) { + perror("fseek"); + return -1; + } + + size_t nread, nwritten; + char buf[1024]; + + while ((nread = read(fileno(p->stdout_file), buf, 1024)) > 0) { + nwritten = write(fd, buf, nread); + /* TODO: what if write doesn't write the whole buffer... */ + if (nwritten < 0) { + perror("write"); + return -1; + } + } + + if (nread < 0) { + perror("read"); + return -1; + } + + return 0; +} + + +/* Return the name that was specified when `p` was started by process_start */ +char* process_get_name(process_info_t *p) { + return p->name; +} + + +/* Terminate process `p`. */ +int process_terminate(process_info_t *p) { + return kill(p->pid, SIGTERM); +} + + +/* Return the exit code of process p. */ +/* On error, return -1. */ +int process_reap(process_info_t *p) { + return WEXITSTATUS(p->status); +} + + +/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */ +void process_cleanup(process_info_t *p) { + fclose(p->stdout_file); + free(p->name); +} + + +/* Move the console cursor one line up and back to the first column. */ +int rewind_cursor() { + printf("\033[1A\033[80D"); +} diff --git a/test/test-runner-unix.h b/test/test-runner-unix.h new file mode 100644 index 00000000..731130db --- /dev/null +++ b/test/test-runner-unix.h @@ -0,0 +1,15 @@ +#ifndef TEST_RUNNER_UNIX_H +#define TEST_RUNNER_UNIX_H + +#include +#include /* FILE */ + +typedef struct { + FILE* stdout_file; + pid_t pid; + char* name; + int status; + int terminated; +} process_info_t; + +#endif /* TEST_RUNNER_UNIX_H */ diff --git a/test/test-runner.c b/test/test-runner.c index cfe69240..6944a468 100644 --- a/test/test-runner.c +++ b/test/test-runner.c @@ -2,7 +2,7 @@ #include "test-runner.h" #include -#include +#include #include #include @@ -176,4 +176,4 @@ int main(int argc, char **argv) { return 0; } -} \ No newline at end of file +} diff --git a/test/test-runner.h b/test/test-runner.h index c1659941..2305d004 100644 --- a/test/test-runner.h +++ b/test/test-runner.h @@ -80,4 +80,4 @@ void process_cleanup(process_info_t *p); /* Move the console cursor one line up and back to the first column. */ int rewind_cursor(); -#endif /* TEST_RUNNER_H_ */ \ No newline at end of file +#endif /* TEST_RUNNER_H_ */