Mercurial > louis > mq > lightsd
changeset 214:ab8a871e92bf
wip command pipe testing
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 02 Aug 2015 16:00:20 -0700 |
parents | f90069882b45 |
children | 7b980a75598d |
files | daemon_module.patch testing_command_pipe.patch |
diffstat | 2 files changed, 429 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/daemon_module.patch Sat Aug 01 23:09:48 2015 -0700 +++ b/daemon_module.patch Sun Aug 02 16:00:20 2015 -0700 @@ -595,7 +595,7 @@ new file mode 100644 --- /dev/null +++ b/tests/core/daemon/test_daemon_update_proctitle.c -@@ -0,0 +1,99 @@ +@@ -0,0 +1,109 @@ +void mock_setproctitle(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); + @@ -685,11 +685,21 @@ + "listening_on(foobar.com:[1234]); " + "lifx_gateways(found=1); " + "bulbs(found=2, on=1); " -+ "clients(connected=1)" ++ "clients(connected=0)" + ); + LGTD_STATS_ADD_AND_UPDATE_PROCTITLE(bulbs_powered_on, 1); ++ if (setproctitle_call_count != 6) { ++ errx(1, "setproctitle should have been called"); ++ } ++ ++ expected = ( ++ "listening_on(foobar.com:[1234]); " ++ "lifx_gateways(found=1); " ++ "bulbs(found=2, on=1); " ++ "clients(connected=1)" ++ ); + LGTD_STATS_ADD_AND_UPDATE_PROCTITLE(clients, 1); -+ if (setproctitle_call_count != 6) { ++ if (setproctitle_call_count != 7) { + errx(1, "setproctitle should have been called"); + } +
--- a/testing_command_pipe.patch Sat Aug 01 23:09:48 2015 -0700 +++ b/testing_command_pipe.patch Sun Aug 02 16:00:20 2015 -0700 @@ -1,5 +1,5 @@ # HG changeset patch -# Parent 4e1471c983f9e4e62394e77cb70fbe07328950da +# Parent 2781c3dbb72d815271a446c90a08da3aef0936d6 diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt @@ -13,6 +13,41 @@ "-DLGTD_BIG_ENDIAN_SYSTEM=${BIG_ENDIAN_SYSTEM}" "-DLGTD_SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P}" +diff --git a/core/pipe.c b/core/pipe.c +--- a/core/pipe.c ++++ b/core/pipe.c +@@ -148,6 +148,14 @@ + jsmn_init(&pipe->client.jsmn_ctx); + } + ++static mode_t ++lgtd_command_pipe_get_umask(void) ++{ ++ mode_t mask = umask(0); ++ umask(mask); ++ return mask; ++} ++ + bool + lgtd_command_pipe_open(const char *path) + { +@@ -171,8 +179,14 @@ + pipe->fd = -1; + + mode_t mode = S_IWUSR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IWGRP; +- if (mkfifo(path, mode) && errno != EEXIST) { +- goto error; ++ if (mkfifo(path, mode)) { ++ if (errno != EEXIST) { ++ goto error; ++ } ++ mode &= ~lgtd_command_pipe_get_umask(); ++ if (chmod(path, mode)) { ++ goto error; ++ } + } + + pipe->fd = open(path, O_RDONLY|O_NONBLOCK); diff --git a/tests/core/daemon/CMakeLists.txt b/tests/core/daemon/CMakeLists.txt --- a/tests/core/daemon/CMakeLists.txt +++ b/tests/core/daemon/CMakeLists.txt @@ -170,11 +205,133 @@ +FOREACH(TEST ${TESTS}) + ADD_PIPE_TEST(${TEST}) +ENDFOREACH() +diff --git a/tests/core/pipe/test_pipe_close.c b/tests/core/pipe/test_pipe_close.c +new file mode 100644 +--- /dev/null ++++ b/tests/core/pipe/test_pipe_close.c +@@ -0,0 +1,117 @@ ++#include "pipe.c" ++ ++#include <sys/tree.h> ++#include <endian.h> ++#include <limits.h> ++ ++#include "lifx/wire_proto.h" ++ ++#define MOCKED_EVENT_NEW ++#define MOCKED_EVBUFFER_NEW ++#define MOCKED_EVENT_DEL ++#define MOCKED_EVBUFFER_FREE ++#define MOCKED_EVENT_FREE ++#include "mock_event2.h" ++#include "mock_gateway.h" ++#include "mock_daemon.h" ++ ++#include "tests_utils.h" ++#include "tests_pipe_utils.h" ++ ++char *tmpdir = NULL; ++ ++void ++cleanup_tmpdir(void) ++{ ++ lgtd_tests_remove_temp_dir(tmpdir); ++} ++ ++struct event * ++event_new(struct event_base *base, ++ evutil_socket_t fd, ++ short events, ++ event_callback_fn cb, ++ void *ctx) ++{ ++ (void)base; ++ (void)fd; ++ (void)events; ++ (void)cb; ++ (void)ctx; ++ ++ return (void *)1; ++} ++ ++struct evbuffer * ++evbuffer_new(void) ++{ ++ return (void *)2; ++} ++ ++static int event_del_call_count = 0; ++ ++int ++event_del(struct event *ev) ++{ ++ (void)ev; ++ ++ event_del_call_count++; ++ ++ return 0; ++} ++ ++static int evbuffer_free_call_count = 0; ++ ++void ++evbuffer_free(struct evbuffer *buf) ++{ ++ (void)buf; ++ ++ evbuffer_free_call_count++; ++} ++ ++static int event_free_call_count = 0; ++ ++void ++event_free(struct event *ev) ++{ ++ (void)ev; ++ ++ event_free_call_count++; ++} ++ ++int ++main(void) ++{ ++ tmpdir = lgtd_tests_make_temp_dir(); ++ atexit(cleanup_tmpdir); ++ ++ char path[PATH_MAX] = { 0 }; ++ snprintf(path, sizeof(path), "%s/lightsd.pipe", tmpdir); ++ if (!lgtd_command_pipe_open(path)) { ++ errx(1, "couldn't open pipe"); ++ } ++ ++ int pipe_fd = SLIST_FIRST(&lgtd_command_pipes)->fd; ++ ++ lgtd_command_pipe_close_all(); ++ ++ if (event_del_call_count != 1) { ++ errx(1, "event_del_call_count = %d", event_del_call_count); ++ } ++ if (evbuffer_free_call_count != 1) { ++ errx(1, "evbuffer_free_call_count = %d", evbuffer_free_call_count); ++ } ++ if (event_free_call_count != 1) { ++ errx(1, "event_free_call_count = %d", event_free_call_count); ++ } ++ struct stat sb; ++ if (fstat(pipe_fd, &sb) != -1 && errno != EBADF) { ++ errx(1, "the pipe file descriptor wasn't closed correctly"); ++ } ++ if (stat(path, &sb) != -1 && errno != ENOENT) { ++ errx(1, "the pipe wasn't removed correctly"); ++ } ++ ++ return 0; ++} diff --git a/tests/core/pipe/test_pipe_open.c b/tests/core/pipe/test_pipe_open.c new file mode 100644 --- /dev/null +++ b/tests/core/pipe/test_pipe_open.c -@@ -0,0 +1,162 @@ +@@ -0,0 +1,171 @@ +#include "pipe.c" + +#include <sys/tree.h> @@ -328,13 +485,269 @@ + + mode_t expected_mode; + expected_mode = S_IFIFO|S_IWUSR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IWGRP; ++ expected_mode &= ~lgtd_command_pipe_get_umask(); + if (sb.st_mode != expected_mode) { + errx( -+ 1, "unexpected mode %#x (expected %hx)", ++ 1, "unexpected mode %o (expected %o)", + sb.st_mode, expected_mode + ); + } + ++ // make sure it's idempotent: ++ if (!lgtd_command_pipe_open(path)) { ++ errx(1, "couldn't open pipe"); ++ } ++ if (event_new_call_count != 1) { ++ errx(1, "event_new_call_count = %d", event_new_call_count); ++ } ++ ++ return 0; ++} +diff --git a/tests/core/pipe/test_pipe_open_fifo_already_exists.c b/tests/core/pipe/test_pipe_open_fifo_already_exists.c +new file mode 100644 +--- /dev/null ++++ b/tests/core/pipe/test_pipe_open_fifo_already_exists.c +@@ -0,0 +1,176 @@ ++#include "pipe.c" ++ ++#include <sys/tree.h> ++#include <endian.h> ++#include <limits.h> ++ ++#include "lifx/wire_proto.h" ++ ++#define MOCKED_EVUTIL_MAKE_SOCKET_NONBLOCKING ++#define MOCKED_EVENT_NEW ++#define MOCKED_EVBUFFER_NEW ++#define MOCKED_EVENT_ADD ++#include "mock_event2.h" ++#include "mock_gateway.h" ++#include "mock_daemon.h" ++ ++#include "tests_utils.h" ++#define MOCKED_CLIENT_OPEN_FROM_PIPE ++#include "tests_pipe_utils.h" ++ ++char *tmpdir = NULL; ++ ++void ++cleanup_tmpdir(void) ++{ ++ lgtd_tests_remove_temp_dir(tmpdir); ++} ++ ++static bool make_socket_nonblocking_call_count = 0; ++ ++int ++evutil_make_socket_nonblocking(evutil_socket_t fd) ++{ ++ if (fd <= 0) { ++ errx(1, "got invalid fd %d in make_socket_nonblocking", fd); ++ } ++ ++ make_socket_nonblocking_call_count++; ++ ++ return 0; ++} ++ ++static int event_new_call_count = 0; ++ ++struct event * ++event_new(struct event_base *base, ++ evutil_socket_t fd, ++ short events, ++ event_callback_fn cb, ++ void *ctx) ++{ ++ if (base != lgtd_ev_base) { ++ errx( ++ 1, "unexpected lgtd_ev_base = %p (expected %p)", ++ base, lgtd_ev_base ++ ); ++ } ++ if (fd <= 0) { ++ errx(1, "got invalid fd %d in event_new", fd); ++ } ++ if (events != (EV_READ|EV_PERSIST)) { ++ errx(1, "got events %#x (expected %#x)", events, EV_READ|EV_PERSIST); ++ } ++ if (cb != lgtd_command_pipe_read_callback) { ++ errx(1, "the read callback wasn't set correctly"); ++ } ++ if (!ctx) { ++ errx(1, "the callback context wasn't set correctly"); ++ } ++ ++ event_new_call_count++; ++ ++ return (void *)1; ++} ++ ++static int evbuffer_new_call_count = 0; ++ ++struct evbuffer * ++evbuffer_new(void) ++{ ++ evbuffer_new_call_count++; ++ ++ return (void *)2; ++} ++ ++static int event_add_call_count = 0; ++ ++int ++event_add(struct event *ev, const struct timeval *timeout) ++{ ++ if (ev != (void *)1) { ++ errx(1, "got unexpected event %p (expected %p)", ev, (void*)1); ++ } ++ ++ if (timeout) { ++ errx(1, "a timeout shouldn't have been passed"); ++ } ++ ++ event_add_call_count++; ++ ++ return 0; ++} ++ ++static int client_open_from_pipe_call_count = 0; ++ ++void ++lgtd_client_open_from_pipe(struct lgtd_client *pipe_client) ++{ ++ if (!pipe_client) { ++ errx(1, "missing pipe_client"); ++ } ++ ++ client_open_from_pipe_call_count++; ++} ++ ++int ++main(void) ++{ ++ tmpdir = lgtd_tests_make_temp_dir(); ++ atexit(cleanup_tmpdir); ++ ++ char path[PATH_MAX] = { 0 }; ++ snprintf(path, sizeof(path), "%s/lightsd.pipe", tmpdir); ++ ++ if (mkfifo(path, 0)) { ++ errx(1, "can't open fifo"); ++ } ++ ++ if (!lgtd_command_pipe_open(path)) { ++ errx(1, "couldn't open pipe"); ++ } ++ ++ if (make_socket_nonblocking_call_count != 1) { ++ errx( ++ 1, "make_socket_nonblocking_call_count = %d", ++ make_socket_nonblocking_call_count ++ ); ++ } ++ if (event_new_call_count != 1) { ++ errx(1, "event_new_call_count = %d", event_new_call_count); ++ } ++ if (evbuffer_new_call_count != 1) { ++ errx(1, "evbuffer_new_call_count = %d", evbuffer_new_call_count); ++ } ++ if (event_add_call_count != 1) { ++ errx(1, "event_add_call_count = %d", event_add_call_count); ++ } ++ if (SLIST_EMPTY(&lgtd_command_pipes)) { ++ errx(1, "the list of command pipes shouldn't be empty"); ++ } ++ ++ struct stat sb; ++ if (stat(path, &sb)) { ++ errx(1, "can't stat pipe %s", path); ++ } ++ ++ mode_t expected_mode; ++ expected_mode = S_IFIFO|S_IWUSR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IWGRP; ++ expected_mode &= ~lgtd_command_pipe_get_umask(); ++ if (sb.st_mode != expected_mode) { ++ errx( ++ 1, "unexpected mode %o (expected %o)", ++ sb.st_mode, expected_mode ++ ); ++ } ++ ++ // make sure it's idempotent: ++ if (!lgtd_command_pipe_open(path)) { ++ errx(1, "couldn't open pipe"); ++ } ++ if (event_new_call_count != 1) { ++ errx(1, "event_new_call_count = %d", event_new_call_count); ++ } ++ ++ return 0; ++} +diff --git a/tests/core/pipe/test_pipe_read_callback.c b/tests/core/pipe/test_pipe_read_callback.c +new file mode 100644 +--- /dev/null ++++ b/tests/core/pipe/test_pipe_read_callback.c +@@ -0,0 +1,61 @@ ++#include "pipe.c" ++ ++#include <sys/tree.h> ++#include <endian.h> ++#include <limits.h> ++ ++#include "lifx/wire_proto.h" ++ ++#define MOCKED_EVENT_NEW ++#define MOCKED_EVBUFFER_NEW ++#include "mock_event2.h" ++#include "mock_gateway.h" ++#include "mock_daemon.h" ++ ++#include "tests_utils.h" ++#include "tests_pipe_utils.h" ++ ++char *tmpdir = NULL; ++ ++void ++cleanup_tmpdir(void) ++{ ++ lgtd_tests_remove_temp_dir(tmpdir); ++} ++ ++struct event * ++event_new(struct event_base *base, ++ evutil_socket_t fd, ++ short events, ++ event_callback_fn cb, ++ void *ctx) ++{ ++ (void)base; ++ (void)fd; ++ (void)events; ++ (void)cb; ++ (void)ctx; ++ ++ return (void *)1; ++} ++ ++struct evbuffer * ++evbuffer_new(void) ++{ ++ return (void *)2; ++} ++ ++int ++main(void) ++{ ++ tmpdir = lgtd_tests_make_temp_dir(); ++ atexit(cleanup_tmpdir); ++ ++ char path[PATH_MAX] = { 0 }; ++ snprintf(path, sizeof(path), "%s/lightsd.pipe", tmpdir); ++ if (!lgtd_command_pipe_open(path)) { ++ errx(1, "couldn't open pipe"); ++ } ++ + return 0; +} diff --git a/tests/core/pipe/tests_pipe_utils.h b/tests/core/pipe/tests_pipe_utils.h