It's nice to keep helper sources separately from tests sources.
It's better for searching files as well as for extending
the test-suite.

Also, there were no need to compile each test with test-*.c files
so I used them to create noinst library and link the tests against it.
Now we don't need to attach test-runner files to each test sources.
---
 configure.ac                     |   3 +-
 tests/Makefile.am                |  46 ++++-----
 tests/test-helpers.c             |  64 ------------
 tests/test-runner.c              | 207 ---------------------------------------
 tests/test-runner.h              |  40 --------
 tests/test-runner/Makefile.am    |  13 +++
 tests/test-runner/test-helpers.c |  64 ++++++++++++
 tests/test-runner/test-runner.c  | 207 +++++++++++++++++++++++++++++++++++++++
 tests/test-runner/test-runner.h  |  40 ++++++++
 9 files changed, 350 insertions(+), 334 deletions(-)
 delete mode 100644 tests/test-helpers.c
 delete mode 100644 tests/test-runner.c
 delete mode 100644 tests/test-runner.h
 create mode 100644 tests/test-runner/Makefile.am
 create mode 100644 tests/test-runner/test-helpers.c
 create mode 100644 tests/test-runner/test-runner.c
 create mode 100644 tests/test-runner/test-runner.h

diff --git a/configure.ac b/configure.ac
index f8be456..09db2e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,5 +146,6 @@ AC_CONFIG_FILES([Makefile
                 src/wayland-scanner.pc
                 src/wayland-version.h
                 protocol/Makefile
-                tests/Makefile])
+                tests/Makefile
+                tests/test-runner/Makefile])
 AC_OUTPUT
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9c673ae..4a999b9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,3 +1,6 @@
+SUBDIRS = test-runner
+test_runner_dir = $(top_builddir)/tests/test-runner
+
 TESTS =                                                \
        array-test                              \
        client-test                             \
@@ -21,38 +24,37 @@ check_PROGRAMS =                            \
 noinst_PROGRAMS =                              \
        fixed-benchmark
 
-test_runner_src = test-runner.c test-runner.h test-helpers.c
-
-array_test_SOURCES = array-test.c $(test_runner_src)
-client_test_SOURCES = client-test.c $(test_runner_src)
-display_test_SOURCES = display-test.c $(test_runner_src)
-connection_test_SOURCES = connection-test.c $(test_runner_src)
-event_loop_test_SOURCES = event-loop-test.c $(test_runner_src)
-fixed_test_SOURCES = fixed-test.c $(test_runner_src)
-list_test_SOURCES = list-test.c $(test_runner_src)
-map_test_SOURCES = map-test.c $(test_runner_src)
-sanity_test_SOURCES = sanity-test.c $(test_runner_src)
-socket_test_SOURCES = socket-test.c $(test_runner_src)
-queue_test_SOURCES = queue-test.c $(test_runner_src)
-signal_test_SOURCES = signal-test.c $(test_runner_src)
-resources_test_SOURCES = resources-test.c $(test_runner_src)
+array_test_SOURCES = array-test.c
+client_test_SOURCES = client-test.c
+display_test_SOURCES = display-test.c
+connection_test_SOURCES = connection-test.c
+event_loop_test_SOURCES = event-loop-test.c
+fixed_test_SOURCES = fixed-test.c
+list_test_SOURCES = list-test.c
+map_test_SOURCES = map-test.c
+sanity_test_SOURCES = sanity-test.c
+socket_test_SOURCES = socket-test.c
+queue_test_SOURCES = queue-test.c
+signal_test_SOURCES = signal-test.c
+resources_test_SOURCES = resources-test.c
 
 fixed_benchmark_SOURCES = fixed-benchmark.c
 
 os_wrappers_test_SOURCES =                     \
        os-wrappers-test.c                      \
-       ../src/wayland-os.c                     \
-       $(test_runner_src)
+       ../src/wayland-os.c
 
-AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src
+AM_CPPFLAGS =                                  \
+       -I$(top_builddir)/src                   \
+       -I$(top_srcdir)/src                     \
+       -I$(test_runner_dir)
 AM_CFLAGS = $(GCC_CFLAGS) $(FFI_CFLAGS)
 LDADD = $(top_builddir)/src/libwayland-util.la \
        $(top_builddir)/src/libwayland-client.la \
        $(top_builddir)/src/libwayland-server.la \
+       $(test_runner_dir)/libtest-runner.la
        -lrt -ldl $(FFI_LIBS)
 
 exec_fd_leak_checker_SOURCES =                 \
-       exec-fd-leak-checker.c                  \
-       test-runner.h                           \
-       test-helpers.c
-exec_fd_leak_checker_LDADD =
+       exec-fd-leak-checker.c
+exec_fd_leak_checker_LDADD = $(test_runner_dir)/libtest-helpers.la
diff --git a/tests/test-helpers.c b/tests/test-helpers.c
deleted file mode 100644
index 4761b09..0000000
--- a/tests/test-helpers.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright © 2012 Collabora, Ltd.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "test-runner.h"
-
-int
-count_open_fds(void)
-{
-       DIR *dir;
-       struct dirent *ent;
-       int count = 0;
-
-       dir = opendir("/proc/self/fd");
-       assert(dir && "opening /proc/self/fd failed.");
-
-       errno = 0;
-       while ((ent = readdir(dir))) {
-               const char *s = ent->d_name;
-               if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
-                       continue;
-               count++;
-       }
-       assert(errno == 0 && "reading /proc/self/fd failed.");
-
-       closedir(dir);
-
-       return count;
-}
-
-void
-exec_fd_leak_check(int nr_expected_fds)
-{
-       const char *exe = "./exec-fd-leak-checker";
-       char number[16] = { 0 };
-
-       snprintf(number, sizeof number - 1, "%d", nr_expected_fds);
-       execl(exe, exe, number, (char *)NULL);
-       assert(0 && "execing fd leak checker failed");
-}
diff --git a/tests/test-runner.c b/tests/test-runner.c
deleted file mode 100644
index 8f3d5d3..0000000
--- a/tests/test-runner.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright © 2012 Intel Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <string.h>
-#include <assert.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include "test-runner.h"
-
-static int num_alloc;
-static void* (*sys_malloc)(size_t);
-static void (*sys_free)(void*);
-static void* (*sys_realloc)(void*, size_t);
-static void* (*sys_calloc)(size_t, size_t);
-
-int leak_check_enabled;
-
-extern const struct test __start_test_section, __stop_test_section;
-
-__attribute__ ((visibility("default"))) void *
-malloc(size_t size)
-{
-       num_alloc++;
-       return sys_malloc(size);
-}
-
-__attribute__ ((visibility("default"))) void
-free(void* mem)
-{
-       if (mem != NULL)
-               num_alloc--;
-       sys_free(mem);
-}
-
-__attribute__ ((visibility("default"))) void *
-realloc(void* mem, size_t size)
-{
-       if (mem == NULL)
-               num_alloc++;
-       return sys_realloc(mem, size);
-}
-
-__attribute__ ((visibility("default"))) void *
-calloc(size_t nmemb, size_t size)
-{
-       if (sys_calloc == NULL)
-               return NULL;
-
-       num_alloc++;
-
-       return sys_calloc(nmemb, size);
-}
-
-static const struct test *
-find_test(const char *name)
-{
-       const struct test *t;
-
-       for (t = &__start_test_section; t < &__stop_test_section; t++)
-               if (strcmp(t->name, name) == 0)
-                       return t;
-
-       return NULL;
-}
-
-static void
-usage(const char *name, int status)
-{
-       const struct test *t;
-
-       fprintf(stderr, "Usage: %s [TEST]\n\n"
-               "With no arguments, run all test.  Specify test case to run\n"
-               "only that test without forking.  Available tests:\n\n",
-               name);
-
-       for (t = &__start_test_section; t < &__stop_test_section; t++)
-               fprintf(stderr, "  %s\n", t->name);
-
-       fprintf(stderr, "\n");
-
-       exit(status);
-}
-
-static void
-run_test(const struct test *t)
-{
-       int cur_alloc = num_alloc;
-       int cur_fds, num_fds;
-
-       cur_fds = count_open_fds();
-       t->run();
-       if (leak_check_enabled) {
-               if (cur_alloc != num_alloc) {
-                       fprintf(stderr, "Memory leak detected in test. "
-                               "Allocated %d blocks, unfreed %d\n", num_alloc,
-                               num_alloc - cur_alloc);
-                       abort();
-               }
-               num_fds = count_open_fds();
-               if (cur_fds != num_fds) {
-                       fprintf(stderr, "fd leak detected in test. "
-                               "Opened %d files, unclosed %d\n", num_fds,
-                               num_fds - cur_fds);
-                       abort();
-               }
-       }
-       exit(EXIT_SUCCESS);
-}
-
-int main(int argc, char *argv[])
-{
-       const struct test *t;
-       pid_t pid;
-       int total, pass;
-       siginfo_t info;
-
-       /* Load system malloc, free, and realloc */
-       sys_calloc = dlsym(RTLD_NEXT, "calloc");
-       sys_realloc = dlsym(RTLD_NEXT, "realloc");
-       sys_malloc = dlsym(RTLD_NEXT, "malloc");
-       sys_free = dlsym(RTLD_NEXT, "free");
-
-       leak_check_enabled = !getenv("NO_ASSERT_LEAK_CHECK");
-
-       if (argc == 2 && strcmp(argv[1], "--help") == 0)
-               usage(argv[0], EXIT_SUCCESS);
-
-       if (argc == 2) {
-               t = find_test(argv[1]);
-               if (t == NULL) {
-                       fprintf(stderr, "unknown test: \"%s\"\n", argv[1]);
-                       usage(argv[0], EXIT_FAILURE);
-               }
-
-               run_test(t);
-       }
-
-       pass = 0;
-       for (t = &__start_test_section; t < &__stop_test_section; t++) {
-               int success = 0;
-
-               pid = fork();
-               assert(pid >= 0);
-
-               if (pid == 0)
-                       run_test(t); /* never returns */
-
-               if (waitid(P_ALL, 0, &info, WEXITED)) {
-                       fprintf(stderr, "waitid failed: %m\n");
-                       abort();
-               }
-
-               fprintf(stderr, "test \"%s\":\t", t->name);
-               switch (info.si_code) {
-               case CLD_EXITED:
-                       fprintf(stderr, "exit status %d", info.si_status);
-                       if (info.si_status == EXIT_SUCCESS)
-                               success = 1;
-                       break;
-               case CLD_KILLED:
-               case CLD_DUMPED:
-                       fprintf(stderr, "signal %d", info.si_status);
-                       break;
-               }
-
-               if (t->must_fail)
-                       success = !success;
-
-               if (success) {
-                       pass++;
-                       fprintf(stderr, ", pass.\n");
-               } else
-                       fprintf(stderr, ", fail.\n");
-       }
-
-       total = &__stop_test_section - &__start_test_section;
-       fprintf(stderr, "%d tests, %d pass, %d fail\n",
-               total, pass, total - pass);
-
-       return pass == total ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/tests/test-runner.h b/tests/test-runner.h
deleted file mode 100644
index 707504c..0000000
--- a/tests/test-runner.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _TEST_RUNNER_H_
-#define _TEST_RUNNER_H_
-
-#ifdef NDEBUG
-#error "Tests must not be built with NDEBUG defined, they rely on assert()."
-#endif
-
-struct test {
-       const char *name;
-       void (*run)(void);
-       int must_fail;
-} __attribute__ ((aligned (16)));
-
-#define TEST(name)                                             \
-       static void name(void);                                 \
-                                                               \
-       const struct test test##name                            \
-                __attribute__ ((section ("test_section"))) = { \
-               #name, name, 0                                  \
-       };                                                      \
-                                                               \
-       static void name(void)
-
-#define FAIL_TEST(name)                                                \
-       static void name(void);                                 \
-                                                               \
-       const struct test test##name                            \
-                __attribute__ ((section ("test_section"))) = { \
-               #name, name, 1                                  \
-       };                                                      \
-                                                               \
-       static void name(void)
-
-int
-count_open_fds(void);
-
-void
-exec_fd_leak_check(int nr_expected_fds); /* never returns */
-
-#endif
diff --git a/tests/test-runner/Makefile.am b/tests/test-runner/Makefile.am
new file mode 100644
index 0000000..b8f1e76
--- /dev/null
+++ b/tests/test-runner/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libtest-runner.la libtest-helpers.la
+
+libtest_runner_la_LDFLAGS = -ldl
+libtest_runner_la_LIBADD = libtest-helpers.la
+libtest_runner_la_SOURCES =    \
+       test-runner.c           \
+       test-runner.h
+
+libtest_helpers_la_SOURCES =   \
+       test-helpers.c
+
+AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src
+AM_CFLAGS = $(GCC_CFLAGS)
diff --git a/tests/test-runner/test-helpers.c b/tests/test-runner/test-helpers.c
new file mode 100644
index 0000000..4761b09
--- /dev/null
+++ b/tests/test-runner/test-helpers.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2012 Collabora, Ltd.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "test-runner.h"
+
+int
+count_open_fds(void)
+{
+       DIR *dir;
+       struct dirent *ent;
+       int count = 0;
+
+       dir = opendir("/proc/self/fd");
+       assert(dir && "opening /proc/self/fd failed.");
+
+       errno = 0;
+       while ((ent = readdir(dir))) {
+               const char *s = ent->d_name;
+               if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
+                       continue;
+               count++;
+       }
+       assert(errno == 0 && "reading /proc/self/fd failed.");
+
+       closedir(dir);
+
+       return count;
+}
+
+void
+exec_fd_leak_check(int nr_expected_fds)
+{
+       const char *exe = "./exec-fd-leak-checker";
+       char number[16] = { 0 };
+
+       snprintf(number, sizeof number - 1, "%d", nr_expected_fds);
+       execl(exe, exe, number, (char *)NULL);
+       assert(0 && "execing fd leak checker failed");
+}
diff --git a/tests/test-runner/test-runner.c b/tests/test-runner/test-runner.c
new file mode 100644
index 0000000..8f3d5d3
--- /dev/null
+++ b/tests/test-runner/test-runner.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include "test-runner.h"
+
+static int num_alloc;
+static void* (*sys_malloc)(size_t);
+static void (*sys_free)(void*);
+static void* (*sys_realloc)(void*, size_t);
+static void* (*sys_calloc)(size_t, size_t);
+
+int leak_check_enabled;
+
+extern const struct test __start_test_section, __stop_test_section;
+
+__attribute__ ((visibility("default"))) void *
+malloc(size_t size)
+{
+       num_alloc++;
+       return sys_malloc(size);
+}
+
+__attribute__ ((visibility("default"))) void
+free(void* mem)
+{
+       if (mem != NULL)
+               num_alloc--;
+       sys_free(mem);
+}
+
+__attribute__ ((visibility("default"))) void *
+realloc(void* mem, size_t size)
+{
+       if (mem == NULL)
+               num_alloc++;
+       return sys_realloc(mem, size);
+}
+
+__attribute__ ((visibility("default"))) void *
+calloc(size_t nmemb, size_t size)
+{
+       if (sys_calloc == NULL)
+               return NULL;
+
+       num_alloc++;
+
+       return sys_calloc(nmemb, size);
+}
+
+static const struct test *
+find_test(const char *name)
+{
+       const struct test *t;
+
+       for (t = &__start_test_section; t < &__stop_test_section; t++)
+               if (strcmp(t->name, name) == 0)
+                       return t;
+
+       return NULL;
+}
+
+static void
+usage(const char *name, int status)
+{
+       const struct test *t;
+
+       fprintf(stderr, "Usage: %s [TEST]\n\n"
+               "With no arguments, run all test.  Specify test case to run\n"
+               "only that test without forking.  Available tests:\n\n",
+               name);
+
+       for (t = &__start_test_section; t < &__stop_test_section; t++)
+               fprintf(stderr, "  %s\n", t->name);
+
+       fprintf(stderr, "\n");
+
+       exit(status);
+}
+
+static void
+run_test(const struct test *t)
+{
+       int cur_alloc = num_alloc;
+       int cur_fds, num_fds;
+
+       cur_fds = count_open_fds();
+       t->run();
+       if (leak_check_enabled) {
+               if (cur_alloc != num_alloc) {
+                       fprintf(stderr, "Memory leak detected in test. "
+                               "Allocated %d blocks, unfreed %d\n", num_alloc,
+                               num_alloc - cur_alloc);
+                       abort();
+               }
+               num_fds = count_open_fds();
+               if (cur_fds != num_fds) {
+                       fprintf(stderr, "fd leak detected in test. "
+                               "Opened %d files, unclosed %d\n", num_fds,
+                               num_fds - cur_fds);
+                       abort();
+               }
+       }
+       exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+       const struct test *t;
+       pid_t pid;
+       int total, pass;
+       siginfo_t info;
+
+       /* Load system malloc, free, and realloc */
+       sys_calloc = dlsym(RTLD_NEXT, "calloc");
+       sys_realloc = dlsym(RTLD_NEXT, "realloc");
+       sys_malloc = dlsym(RTLD_NEXT, "malloc");
+       sys_free = dlsym(RTLD_NEXT, "free");
+
+       leak_check_enabled = !getenv("NO_ASSERT_LEAK_CHECK");
+
+       if (argc == 2 && strcmp(argv[1], "--help") == 0)
+               usage(argv[0], EXIT_SUCCESS);
+
+       if (argc == 2) {
+               t = find_test(argv[1]);
+               if (t == NULL) {
+                       fprintf(stderr, "unknown test: \"%s\"\n", argv[1]);
+                       usage(argv[0], EXIT_FAILURE);
+               }
+
+               run_test(t);
+       }
+
+       pass = 0;
+       for (t = &__start_test_section; t < &__stop_test_section; t++) {
+               int success = 0;
+
+               pid = fork();
+               assert(pid >= 0);
+
+               if (pid == 0)
+                       run_test(t); /* never returns */
+
+               if (waitid(P_ALL, 0, &info, WEXITED)) {
+                       fprintf(stderr, "waitid failed: %m\n");
+                       abort();
+               }
+
+               fprintf(stderr, "test \"%s\":\t", t->name);
+               switch (info.si_code) {
+               case CLD_EXITED:
+                       fprintf(stderr, "exit status %d", info.si_status);
+                       if (info.si_status == EXIT_SUCCESS)
+                               success = 1;
+                       break;
+               case CLD_KILLED:
+               case CLD_DUMPED:
+                       fprintf(stderr, "signal %d", info.si_status);
+                       break;
+               }
+
+               if (t->must_fail)
+                       success = !success;
+
+               if (success) {
+                       pass++;
+                       fprintf(stderr, ", pass.\n");
+               } else
+                       fprintf(stderr, ", fail.\n");
+       }
+
+       total = &__stop_test_section - &__start_test_section;
+       fprintf(stderr, "%d tests, %d pass, %d fail\n",
+               total, pass, total - pass);
+
+       return pass == total ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/test-runner/test-runner.h b/tests/test-runner/test-runner.h
new file mode 100644
index 0000000..707504c
--- /dev/null
+++ b/tests/test-runner/test-runner.h
@@ -0,0 +1,40 @@
+#ifndef _TEST_RUNNER_H_
+#define _TEST_RUNNER_H_
+
+#ifdef NDEBUG
+#error "Tests must not be built with NDEBUG defined, they rely on assert()."
+#endif
+
+struct test {
+       const char *name;
+       void (*run)(void);
+       int must_fail;
+} __attribute__ ((aligned (16)));
+
+#define TEST(name)                                             \
+       static void name(void);                                 \
+                                                               \
+       const struct test test##name                            \
+                __attribute__ ((section ("test_section"))) = { \
+               #name, name, 0                                  \
+       };                                                      \
+                                                               \
+       static void name(void)
+
+#define FAIL_TEST(name)                                                \
+       static void name(void);                                 \
+                                                               \
+       const struct test test##name                            \
+                __attribute__ ((section ("test_section"))) = { \
+               #name, name, 1                                  \
+       };                                                      \
+                                                               \
+       static void name(void)
+
+int
+count_open_fds(void);
+
+void
+exec_fd_leak_check(int nr_expected_fds); /* never returns */
+
+#endif
-- 
1.8.4.2

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to