[PATCH] tests: move test-runner into subdirectory

Marek Ch mchqwerty at gmail.com
Tue Nov 5 01:03:55 PST 2013


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.3.1



More information about the wayland-devel mailing list