Adds basic support for optionally outputting in the Test Anything Protocol (TAP) format.
This format is a bit older and simplistic, but certain tools handle it well. https://testanything.org/ Signed-off-by: Jon A. Cruz <j...@osg.samsung.com> --- Makefile.am | 2 + tools/zunitc/inc/zunitc/zunitc.h | 9 ++ tools/zunitc/src/zuc_tap_logger.c | 262 ++++++++++++++++++++++++++++++++++++++ tools/zunitc/src/zuc_tap_logger.h | 36 ++++++ tools/zunitc/src/zunitc_impl.c | 13 ++ 5 files changed, 322 insertions(+) create mode 100644 tools/zunitc/src/zuc_tap_logger.c create mode 100644 tools/zunitc/src/zuc_tap_logger.h diff --git a/Makefile.am b/Makefile.am index 094ee23..1333b8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -962,6 +962,8 @@ libzunitc_la_SOURCES = \ tools/zunitc/src/zuc_context.h \ tools/zunitc/src/zuc_event.h \ tools/zunitc/src/zuc_event_listener.h \ + tools/zunitc/src/zuc_tap_logger.c \ + tools/zunitc/src/zuc_tap_logger.h \ tools/zunitc/src/zuc_types.h \ tools/zunitc/src/zunitc_impl.c diff --git a/tools/zunitc/inc/zunitc/zunitc.h b/tools/zunitc/inc/zunitc/zunitc.h index ff01323..18f75c2 100644 --- a/tools/zunitc/inc/zunitc/zunitc.h +++ b/tools/zunitc/inc/zunitc/zunitc.h @@ -232,6 +232,15 @@ void zuc_set_spawn(bool spawn); /** + * Enables output in the Test Anything Protocol (TAP) format. + * https://testanything.org/ + * + * @param enable true to generate TAP output, false to disable. + */ +void +zuc_set_output_tap(bool enable); + +/** * Defines a test case that can be registered to run. */ #define ZUC_TEST(tcase, test) \ diff --git a/tools/zunitc/src/zuc_tap_logger.c b/tools/zunitc/src/zuc_tap_logger.c new file mode 100644 index 0000000..3e6d687 --- /dev/null +++ b/tools/zunitc/src/zuc_tap_logger.c @@ -0,0 +1,262 @@ +/* + * Copyright © 2015 Samsung Electronics Co., 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 "config.h" + +#include "zuc_tap_logger.h" + +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "shared/zalloc.h" +#include "zuc_event_listener.h" +#include "zuc_types.h" +#include "zunitc/zunitc_impl.h" + +#define LOG_FNAME "test_detail.tap" + +/** + * Internal data for tracking and proper output. + */ +struct tap_data { + int fd; /**< file descriptor to output to. */ + int id; /**< counter id of the current test. */ +}; + +/** + * Helper that outputs the detail of a specific failure event. + * + * @param fd the file descriptor to write to. + * @param event the event to write the details of. + */ +static void +emit_event(int fd, struct zuc_event *event); + +static void +destroy(void *data); + +static void +run_started(void *data, int live_case_count, int live_test_count, + int disabled_count); + +static void +run_ended(void *data, int case_count, struct zuc_case **cases, + int live_case_count, int live_test_count, int total_passed, + int total_failed, int total_disabled, long total_elapsed); + +static void +test_ended(void *data, struct zuc_test *test); + +static void +test_disabled(void *data, struct zuc_test *test); + +struct zuc_event_listener * +zuc_tap_logger_create(void) +{ + struct zuc_event_listener *listener = + zalloc(sizeof(struct zuc_event_listener)); + + listener->data = zalloc(sizeof(struct tap_data)); + ((struct tap_data *)listener->data)->fd = -1; + listener->destroy = destroy; + listener->run_started = run_started; + listener->run_ended = run_ended; + listener->test_ended = test_ended; + listener->test_disabled = test_disabled; + + return listener; +} + +void +destroy(void *data) +{ + free(data); +} + +void +run_started(void *data, int live_case_count, int live_test_count, + int disabled_count) +{ + struct tap_data *tdata = data; + tdata->fd = open(LOG_FNAME, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + tdata->id = 0; + dprintf(tdata->fd, "TAP version 13\n"); + dprintf(tdata->fd, "1..%d\n", live_test_count + disabled_count); +} + +void +run_ended(void *data, int case_count, struct zuc_case **cases, + int live_case_count, int live_test_count, int total_passed, + int total_failed, int total_disabled,long total_elapsed) +{ + struct tap_data *tdata = data; + if ((tdata->fd != fileno(stdout)) + && (tdata->fd != fileno(stderr)) + && (tdata->fd != -1)) { + close(tdata->fd); + tdata->fd = -1; + } +} + +void +test_ended(void *data, struct zuc_test *test) +{ + struct tap_data *tdata = data; + bool bad = test->failed || test->fatal; + tdata->id++; + if (bad) + dprintf(tdata->fd, "not ok %d - %s.%s\n", + tdata->id, + test->test_case->name, + test->name); + else if (test->skipped) + dprintf(tdata->fd, "ok %d - # SKIP at runtime %s.%s\n", + tdata->id, + test->test_case->name, + test->name); + else + dprintf(tdata->fd, "ok %d - %s.%s\n", + tdata->id, + test->test_case->name, + test->name); + + if ((bad || test->skipped) && test->events) { + struct zuc_event *evt; + dprintf(tdata->fd, " ---\n"); + for (evt = test->events; evt; evt = evt->next) + emit_event(tdata->fd, evt); + dprintf(tdata->fd, " ...\n"); + } +} + +void +test_disabled(void *data, struct zuc_test *test) +{ + struct tap_data *tdata = data; + tdata->id++; + dprintf(tdata->fd, "ok %d - # SKIP disabled %s.%s\n", + tdata->id, + test->test_case->name, + test->name); +} + +void +emit_event(int fd, struct zuc_event *event) +{ + dprintf(fd, " - message: '"); + + switch (event->op) { + case ZUC_OP_TRUE: + dprintf(fd, "%s:%d: error: Value of: %s", + event->file, event->line, event->expr1); + break; + case ZUC_OP_FALSE: + dprintf(fd, "%s:%d: error: Value of: %s", + event->file, event->line, event->expr1); + break; + case ZUC_OP_EQ: + dprintf(fd, "%s:%d: error: Value of: %s", + event->file, event->line, event->expr2); + break; + case ZUC_OP_TERMINATE: + dprintf(fd, "%s:%d: error: %s", + event->file, event->line, event->expr1); + break; + case ZUC_OP_TRACEPOINT: + dprintf(fd, "%s:%d: note: %s", + event->file, event->line, event->expr1); + break; + default: + dprintf(fd, "%s:%d: error", event->file, event->line); + } + dprintf(fd, "'\n"); + + if ((event->op != ZUC_OP_TRACEPOINT) + && ((event->op != ZUC_OP_TERMINATE) || (event->val1 < 2))) + dprintf(fd, " severity: fail\n"); + + if ((event->op != ZUC_OP_TRACEPOINT) && (event->op != ZUC_OP_TERMINATE)) + dprintf(fd, " data:\n"); + + switch (event->op) { + case ZUC_OP_TRUE: + dprintf(fd, " got : false\n"); + dprintf(fd, " expected: true\n"); + break; + case ZUC_OP_FALSE: + dprintf(fd, " got : true\n"); + dprintf(fd, " expected: false\n"); + break; + case ZUC_OP_NULL: + dprintf(fd, " got : %s\n", event->expr1); + dprintf(fd, " which_is: %p\n", (void *)event->val1); + dprintf(fd, " expected: %p\n", NULL); + break; + case ZUC_OP_NOT_NULL: + dprintf(fd, " got : %s\n", event->expr1); + dprintf(fd, " which_is: %p\n", (void *)event->val1); + dprintf(fd, " expected: not %p\n", NULL); + break; + case ZUC_OP_EQ: + if (event->valtype == ZUC_VAL_CSTR) { + dprintf(fd, " got : %s\n", + (char *)event->val2); + dprintf(fd, " expected: %s\n", event->expr1); + dprintf(fd, " which_is: %s\n", + (char *)event->val1); + } else { + dprintf(fd, " got : %ld\n", event->val2); + dprintf(fd, " expected: %s\n", event->expr1); + dprintf(fd, " which_is: %ld\n", event->val1); + } + break; + case ZUC_OP_NE: + if (event->valtype == ZUC_VAL_CSTR) { + dprintf(fd, " got : %s == %s\n", + (char *)event->val1, (char *)event->val2); + dprintf(fd, " expected: (%s) %s (%s)\n", + event->expr1, zuc_get_opstr(event->op), + event->expr2); + } else { + dprintf(fd, " got : %ld vs %ld\n", + event->val1, event->val2); + dprintf(fd, " expected: (%s) %s (%s)\n", + event->expr1, zuc_get_opstr(event->op), + event->expr2); + } + break; + case ZUC_OP_TERMINATE: /* fallthrough */ + case ZUC_OP_TRACEPOINT: + break; + default: + dprintf(fd, " got : %ld vs %ld\n", + event->val1, event->val2); + dprintf(fd, " expected: (%s) %s (%s)\n", + event->expr1, zuc_get_opstr(event->op), event->expr2); + } +} diff --git a/tools/zunitc/src/zuc_tap_logger.h b/tools/zunitc/src/zuc_tap_logger.h new file mode 100644 index 0000000..1b62e10 --- /dev/null +++ b/tools/zunitc/src/zuc_tap_logger.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2015 Samsung Electronics Co., 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. + */ + +#ifndef ZUC_TAP_LOGGER_H +#define ZUC_TAP_LOGGER_H + +struct zuc_event_listener; + +/** + * Creates a new logger that outputs data in the Test Anything Protocol + * (TAP) format. + * https://testanything.org/ + */ +struct zuc_event_listener * +zuc_tap_logger_create(void); + +#endif /* ZUC_TAP_LOGGER_H */ diff --git a/tools/zunitc/src/zunitc_impl.c b/tools/zunitc/src/zunitc_impl.c index 776a30b..94c572a 100644 --- a/tools/zunitc/src/zunitc_impl.c +++ b/tools/zunitc/src/zunitc_impl.c @@ -43,6 +43,7 @@ #include "zuc_collector.h" #include "zuc_context.h" #include "zuc_event_listener.h" +#include "zuc_tap_logger.h" #include "shared/config-parser.h" #include "shared/zalloc.h" @@ -288,6 +289,12 @@ zuc_set_break_on_failure(bool break_on_failure) g_ctx.break_on_failure = break_on_failure; } +void +zuc_set_output_tap(bool enable) +{ + g_ctx.output_tap = enable; +} + const char * zuc_get_program_name(void) { @@ -310,6 +317,7 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) int opt_repeat = 0; int opt_random = 0; int opt_break_on_failure = 0; + int opt_tap = 0; char *opt_filter = NULL; char *help_param = NULL; @@ -322,6 +330,7 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) { WESTON_OPTION_INTEGER, "zuc-random", 0, &opt_random }, { WESTON_OPTION_BOOLEAN, "zuc-break-on-failure", 0, &opt_break_on_failure }, + { WESTON_OPTION_BOOLEAN, "zuc-output-tap", 0, &opt_tap }, { WESTON_OPTION_STRING, "zuc-filter", 0, &opt_filter }, }; @@ -410,6 +419,7 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) " --zuc-filter=FILTER\n" " --zuc-list-tests\n" " --zuc-nofork\n" + " --zuc-output-tap\n" " --zuc-output-xml\n" " --zuc-random=N [0|1|<seed number>]\n" " --zuc-repeat=N\n" @@ -426,6 +436,7 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) zuc_set_random(opt_random); zuc_set_spawn(!opt_nofork); zuc_set_break_on_failure(opt_break_on_failure); + zuc_set_output_tap(opt_tap); rc = EXIT_SUCCESS; } @@ -958,6 +969,8 @@ zucimpl_run_tests(void) if (g_ctx.listeners == NULL) { zuc_add_event_listener(zuc_collector_create(&(g_ctx.fds[1]))); zuc_add_event_listener(zuc_base_logger_create()); + if (g_ctx.output_tap) + zuc_add_event_listener(zuc_tap_logger_create()); } if (g_ctx.case_count < 1) { -- 2.1.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel