diff --git a/tests/sanity-test.c b/tests/sanity-test.c index 1a33c12..e614cfb 100644 --- a/tests/sanity-test.c +++ b/tests/sanity-test.c @@ -25,7 +25,9 @@ #include #include +#include #include +#include #include #include @@ -181,6 +183,65 @@ FAIL_TEST(tc_client_fd_leaks_exec) display_destroy(d); } +static char * +map_file(int fd, size_t *len) +{ + char *data; + + *len = lseek(fd, 0, SEEK_END); + data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0); + assert(data != MAP_FAILED && "Failed to mmap file"); + + return data; +} + +static void +sanity_client_log(void) +{ + char *log; + size_t log_len; + char *wayland_socket = strdup(getenv("WAYLAND_SOCKET")); + char *xdg_runtime_dir = strdup(getenv("XDG_RUNTIME_DIR")); + + unsetenv("WAYLAND_SOCKET"); + unsetenv("XDG_RUNTIME_DIR"); + + /* Try to connect to the default wayland display, which should fail since + * we have neither WAYLAND_SOCKET nor XDG_RUNTIME_DIR. */ + assert(!wl_display_connect(NULL)); + + /* Check that the client log contains some mention of XDG_RUNTIME_DIR. */ + log = map_file(client_log_fd, &log_len); + assert(strstr(log, "XDG_RUNTIME_DIR")); + munmap(log, log_len); + + /* Reset the environment variables we unset for the test. The test harness + * leak checker cares about the value of WAYLAND_SOCKET during teardown for + * correct fd accounting. */ + setenv("XDG_RUNTIME_DIR", xdg_runtime_dir, 0); + setenv("WAYLAND_SOCKET", wayland_socket, 0); + free(xdg_runtime_dir); + free(wayland_socket); +} + +TEST(tc_client_log) +{ + struct display *d = display_create(); + struct client_info *ci; + char *log; + size_t log_len; + + ci = client_create_noarg(d, sanity_client_log); + display_run(d); + + /* Check that the client log contains some mention of XDG_RUNTIME_DIR. */ + log = map_file(ci->log_fd, &log_len); + assert(strstr(log, "XDG_RUNTIME_DIR")); + munmap(log, log_len); + + display_destroy(d); +} + FAIL_TEST(timeout_tst) { test_set_timeout(1); diff --git a/tests/test-compositor.c b/tests/test-compositor.c index 103ddc8..587bc2b 100644 --- a/tests/test-compositor.c +++ b/tests/test-compositor.c @@ -40,6 +40,8 @@ #include "test-runner.h" #include "test-compositor.h" +int client_log_fd = -1; + /* --- Protocol --- */ struct test_compositor; @@ -155,9 +157,21 @@ client_destroyed(struct wl_listener *listener, void *data) ci->wl_client = NULL; } +static void +client_log_handler(const char *fmt, va_list arg) +{ + va_list arg_copy; + + va_copy(arg_copy, arg); + vdprintf(client_log_fd, fmt, arg_copy); + va_end(arg_copy); + + vfprintf(stderr, fmt, arg); +} + static void run_client(void (*client_main)(void *data), void *data, - int wayland_sock, int client_pipe) + int wayland_sock, int client_pipe, int log_fd) { char s[8]; int cur_fds; @@ -173,6 +187,10 @@ run_client(void (*client_main)(void *data), void *data, snprintf(s, sizeof s, "%d", wayland_sock); setenv("WAYLAND_SOCKET", s, 0); + /* Capture the log to the specified file descriptor. */ + client_log_fd = log_fd; + wl_log_set_handler_client(client_log_handler); + cur_fds = count_open_fds(); client_main(data); @@ -188,6 +206,18 @@ run_client(void (*client_main)(void *data), void *data, check_fd_leaks(cur_fds); } +static int +create_log_fd(void) +{ + char logname[] = "/tmp/wayland-tests-log-XXXXXX"; + int log_fd = mkstemp(logname); + + if (log_fd >= 0) + unlink(logname); + + return log_fd; +} + static struct client_info * display_create_client(struct display *d, void (*client_main)(void *data), @@ -199,11 +229,15 @@ display_create_client(struct display *d, pid_t pid; int can_continue = 0; struct client_info *cl; + int log_fd; assert(pipe(pipe_cli) == 0 && "Failed creating pipe"); assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_wayl) == 0 && "Failed creating socket pair"); + log_fd = create_log_fd(); + assert(log_fd >= 0 && "Failed to create log fd"); + pid = fork(); assert(pid != -1 && "Fork failed"); @@ -211,10 +245,11 @@ display_create_client(struct display *d, close(sock_wayl[1]); close(pipe_cli[1]); - run_client(client_main, data, sock_wayl[0], pipe_cli[0]); + run_client(client_main, data, sock_wayl[0], pipe_cli[0], log_fd); close(sock_wayl[0]); close(pipe_cli[0]); + close(log_fd); exit(0); } @@ -231,6 +266,7 @@ display_create_client(struct display *d, cl->name = name; cl->pid = pid; cl->pipe = pipe_cli[1]; + cl->log_fd = log_fd; cl->destroy_listener.notify = &client_destroyed; cl->wl_client = wl_client_create(d->wl_display, sock_wayl[1]); @@ -407,6 +443,7 @@ display_destroy(struct display *d) } close(cl->pipe); + close(cl->log_fd); free(cl); } diff --git a/tests/test-compositor.h b/tests/test-compositor.h index 7b350fe..b681b09 100644 --- a/tests/test-compositor.h +++ b/tests/test-compositor.h @@ -43,6 +43,7 @@ struct client_info { struct wl_list link; void *data; /* for arbitrary use */ + int log_fd; }; struct display { @@ -106,6 +107,9 @@ void display_post_resume_events(struct display *d); * it then reruns the display. */ void display_resume(struct display *d); +/* The file descriptor containing the client log. This is only valid in the + * test client processes. */ +extern int client_log_fd; struct client_info *client_create_with_name(struct display *d, void (*client_main)(void *data),