[PATCH 1/3] Add support for table-driven testing.
Eoff, Ullysses A
ullysses.a.eoff at intel.com
Tue Sep 10 10:37:58 PDT 2013
> -----Original Message-----
> From: wayland-devel-bounces+ullysses.a.eoff=intel.com at lists.freedesktop.org [mailto:wayland-devel-
> bounces+ullysses.a.eoff=intel.com at lists.freedesktop.org] On Behalf Of Sam Spilsbury
> Sent: Tuesday, September 10, 2013 9:15 AM
> To: wayland-devel at lists.freedesktop.org
> Cc: Sam Spilsbury
> Subject: [PATCH 1/3] Add support for table-driven testing.
>
> The new TEST_P macro takes a function name and a "data" argument to
> point to an arbitrary array of known size of test data. This allows
> multiple tests to be run with different datasets. The array is stored
> as a void * but advanced by a known size on each iteration.
>
> The data for each invocation of the test is provided as a "data" argument,
> it is the responsibility of the test to cast it to something sensible.
> ---
> tests/weston-test-runner.c | 117 ++++++++++++++++++++++++++++-----------------
> tests/weston-test-runner.h | 52 +++++++++++++-------
> 2 files changed, 108 insertions(+), 61 deletions(-)
>
> diff --git a/tests/weston-test-runner.c b/tests/weston-test-runner.c
> index 27ea9e4..1eb93ea 100644
> --- a/tests/weston-test-runner.c
> +++ b/tests/weston-test-runner.c
> @@ -46,18 +46,81 @@ find_test(const char *name)
> }
>
> static void
> -run_test(const struct weston_test *t)
> +run_test(const struct weston_test *t, void *data)
> {
> - t->run();
> + t->run(data);
> exit(EXIT_SUCCESS);
> }
>
> +static int
> +exec_and_report_test(const struct weston_test *t, void *test_data, int iteration)
> +{
> + int success = 0;
> + int hardfail = 0;
> + siginfo_t info;
> +
> + pid_t pid = fork();
> + assert(pid >= 0);
> +
> + if (pid == 0)
> + run_test(t, test_data); /* never returns */
> +
> + if (waitid(P_ALL, 0, &info, WEXITED)) {
> + fprintf(stderr, "waitid failed: %m\n");
> + abort();
> + }
> +
> + if (test_data)
> + fprintf(stderr, "test \"%s/%i\":\t", t->name, iteration);
> + else
> + 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);
> + if (info.si_status != SIGABRT)
> + hardfail = 1;
> + break;
> + }
> +
> + if (t->must_fail)
> + success = !success;
> +
> + if (success && !hardfail) {
> + fprintf(stderr, ", pass.\n");
> + return 1;
> + } else {
> + fprintf(stderr, ", fail.\n");
> + return 0;
> + }
> +}
> +
> +/* Returns number of tests and number of pass / fail in param args */
> +static int
> +iterate_test(const struct weston_test *t, int *passed)
> +{
> + int i;
> + void *current_test_data = (void *) t->table_data;
> + for (i = 0; i < t->n_elements; ++i, current_test_data += t->element_size)
> + {
> + if (exec_and_report_test(t, current_test_data, i))
> + ++(*passed);
> + }
> +
> + return t->n_elements;
> +}
> +
> int main(int argc, char *argv[])
> {
> const struct weston_test *t;
> - pid_t pid;
> - int total, pass;
> - siginfo_t info;
> + int total = 0;
> + int pass = 0;
>
> if (argc == 2) {
> t = find_test(argv[1]);
> @@ -66,51 +129,15 @@ int main(int argc, char *argv[])
> exit(EXIT_FAILURE);
> }
>
> - run_test(t);
> + run_test(t, (void *) t->table_data);
Should we be iterating though each table_data element here, too?
> }
>
> - pass = 0;
> for (t = &__start_test_section; t < &__stop_test_section; t++) {
> - int success = 0;
> - int hardfail = 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);
> - if (info.si_status != SIGABRT)
> - hardfail = 1;
> - break;
> - }
> -
> - if (t->must_fail)
> - success = !success;
> -
> - if (success && !hardfail) {
> - pass++;
> - fprintf(stderr, ", pass.\n");
> - } else
> - fprintf(stderr, ", fail.\n");
> + int number_passed_in_test = 0;
> + total += iterate_test(t, &number_passed_in_test);
> + pass += number_passed_in_test;
> }
>
> - total = &__stop_test_section - &__start_test_section;
> fprintf(stderr, "%d tests, %d pass, %d fail\n",
> total, pass, total - pass);
>
> diff --git a/tests/weston-test-runner.h b/tests/weston-test-runner.h
> index 41df386..457cf31 100644
> --- a/tests/weston-test-runner.h
> +++ b/tests/weston-test-runner.h
> @@ -1,5 +1,6 @@
> /*
> * Copyright © 2012 Intel Corporation
> + * Copyright © 2013 Sam Spilsbury <smspillaz at gmail.com>
> *
> * Permission to use, copy, modify, distribute, and sell this software and
> * its documentation for any purpose is hereby granted without fee, provided
> @@ -23,34 +24,53 @@
> #ifndef _WESTON_TEST_RUNNER_H_
> #define _WESTON_TEST_RUNNER_H_
>
> +#include <stdlib.h>
> +
> #ifdef NDEBUG
> #error "Tests must not be built with NDEBUG defined, they rely on assert()."
> #endif
>
> struct weston_test {
> const char *name;
> - void (*run)(void);
> + void (*run)(void *);
> + const void *table_data;
> + size_t element_size;
> + int n_elements;
> int must_fail;
> -} __attribute__ ((aligned (16)));
> +} __attribute__ ((aligned (32)));
>
> -#define TEST(name) \
> - static void name(void); \
> +#define TEST_BEGIN(name, arg) \
> + static void name(arg)
> +
> +#define TEST_COMMON(func, name, ret, data, size, n_elem) \
> + static void func(void *); \
> \
> const struct weston_test test##name \
> - __attribute__ ((section ("test_section"))) = { \
> - #name, name, 0 \
> - }; \
> - \
> - static void name(void)
> + __attribute__ ((section ("test_section"))) = \
> + { \
> + #name, func, data, size, n_elem, ret \
> + };
>
> -#define FAIL_TEST(name) \
> +#define NO_ARG_TEST(name, ret) \
> + TEST_COMMON(wrap##name, name, ret, NULL, 0, 1) \
> static void name(void); \
> + static void wrap##name(void *data) \
> + { \
> + (void) data; \
> + name(); \
> + } \
> \
> - const struct weston_test test##name \
> - __attribute__ ((section ("test_section"))) = { \
> - #name, name, 1 \
> - }; \
> - \
> - static void name(void)
> + TEST_BEGIN(name, void)
> +
> +#define ARG_TEST(name, ret, test_data) \
> + TEST_COMMON(name, name, ret, test_data, \
> + sizeof(test_data[0]), \
> + sizeof(test_data) / sizeof (test_data[0])) \
> + TEST_BEGIN(name, void *data) \
> +
> +#define TEST(name) NO_ARG_TEST(name, 0)
> +#define FAIL_TEST(name) NO_ARG_TEST(name, 1)
> +#define TEST_P(name, data) ARG_TEST(name, 0, data)
> +#define FAIL_TEST_P(name, data) ARG_TEST(name, 1, data)
>
> #endif
> --
> 1.8.3.2
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list