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

Reply via email to